1 /*
2 * This file is part of the Yices SMT Solver.
3 * Copyright (C) 2017 SRI International.
4 *
5 * Yices is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Yices is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Yices. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /*
20 * TERM MANAGER
21 */
22
23 #include <stdint.h>
24 #include <assert.h>
25
26 #include "terms/bit_term_conversion.h"
27 #include "terms/bv64_constants.h"
28 #include "terms/bv_constants.h"
29 #include "terms/bvarith64_buffer_terms.h"
30 #include "terms/bvarith_buffer_terms.h"
31 #include "terms/rba_buffer_terms.h"
32 #include "terms/term_manager.h"
33 #include "terms/term_utils.h"
34 #include "utils/bit_tricks.h"
35 #include "utils/int_array_sort.h"
36 #include "utils/int_vectors.h"
37 #include "utils/memalloc.h"
38
39
40
41 /************************
42 * GENERAL OPERATIONS *
43 ***********************/
44
45 /*
46 * Initialization:
47 * - terms = attached term table
48 */
init_term_manager(term_manager_t * manager,term_table_t * terms)49 void init_term_manager(term_manager_t *manager, term_table_t *terms) {
50 manager->terms = terms;
51 manager->types = terms->types;
52 manager->pprods = terms->pprods;
53
54 manager->arith_buffer = NULL;
55 manager->bvarith_buffer = NULL;
56 manager->bvarith64_buffer = NULL;
57 // manager->bvarith64_aux_buffer = NULL;
58 manager->bvlogic_buffer = NULL;
59 manager->pp_buffer = NULL;
60
61 manager->bvarith_store = NULL;
62 manager->bvarith64_store = NULL;
63 manager->nodes = NULL;
64
65 q_init(&manager->r0);
66 init_bvconstant(&manager->bv0);
67 init_bvconstant(&manager->bv1);
68 init_bvconstant(&manager->bv2);
69 init_ivector(&manager->vector0, 10);
70
71 manager->simplify_ite = true;
72 manager->simplify_bveq1 = true;
73 }
74
75
76 /*
77 * Access to the internal stores:
78 * - the store is allocated and initialized if needed
79 */
term_manager_get_nodes(term_manager_t * manager)80 node_table_t *term_manager_get_nodes(term_manager_t *manager) {
81 node_table_t *tmp;
82
83 tmp = manager->nodes;
84 if (tmp == NULL) {
85 tmp = (node_table_t *) safe_malloc(sizeof(node_table_t));
86 init_node_table(tmp, 0);
87 manager->nodes = tmp;
88 }
89
90 return tmp;
91 }
92
term_manager_get_bvarith_store(term_manager_t * manager)93 object_store_t *term_manager_get_bvarith_store(term_manager_t *manager) {
94 object_store_t *tmp;
95
96 tmp = manager->bvarith_store;
97 if (tmp == NULL) {
98 tmp = (object_store_t *) safe_malloc(sizeof(object_store_t));
99 init_bvmlist_store(tmp);
100 manager->bvarith_store = tmp;
101 }
102
103 return tmp;
104 }
105
term_manager_get_bvarith64_store(term_manager_t * manager)106 object_store_t *term_manager_get_bvarith64_store(term_manager_t *manager) {
107 object_store_t *tmp;
108
109 tmp = manager->bvarith64_store;
110 if (tmp == NULL) {
111 tmp = (object_store_t *) safe_malloc(sizeof(object_store_t));
112 init_bvmlist64_store(tmp);
113 manager->bvarith64_store = tmp;
114 }
115
116 return tmp;
117 }
118
119
120 /*
121 * Access to the internal buffers:
122 * - they are allocated and initialized if needed (and the store they need too)
123 */
term_manager_get_arith_buffer(term_manager_t * manager)124 rba_buffer_t *term_manager_get_arith_buffer(term_manager_t *manager) {
125 rba_buffer_t *tmp;
126
127 tmp = manager->arith_buffer;
128 if (tmp == NULL) {
129 tmp = (rba_buffer_t *) safe_malloc(sizeof(rba_buffer_t));
130 init_rba_buffer(tmp, manager->pprods);
131 manager->arith_buffer = tmp;
132 }
133
134 return tmp;
135 }
136
term_manager_get_bvarith_buffer(term_manager_t * manager)137 bvarith_buffer_t *term_manager_get_bvarith_buffer(term_manager_t *manager) {
138 bvarith_buffer_t *tmp;
139 object_store_t *mstore;
140
141 tmp = manager->bvarith_buffer;
142 if (tmp == NULL) {
143 mstore = term_manager_get_bvarith_store(manager);
144 tmp = (bvarith_buffer_t *) safe_malloc(sizeof(bvarith_buffer_t));
145 init_bvarith_buffer(tmp, manager->pprods, mstore);
146 manager->bvarith_buffer = tmp;
147 }
148
149 return tmp;
150 }
151
term_manager_get_bvarith64_buffer(term_manager_t * manager)152 bvarith64_buffer_t *term_manager_get_bvarith64_buffer(term_manager_t *manager) {
153 bvarith64_buffer_t *tmp;
154 object_store_t *mstore;
155
156 tmp = manager->bvarith64_buffer;
157 if (tmp == NULL) {
158 mstore = term_manager_get_bvarith64_store(manager);
159 tmp = (bvarith64_buffer_t *) safe_malloc(sizeof(bvarith64_buffer_t));
160 init_bvarith64_buffer(tmp, manager->pprods, mstore);
161 manager->bvarith64_buffer = tmp;
162 }
163
164 return tmp;
165 }
166
term_manager_get_bvlogic_buffer(term_manager_t * manager)167 bvlogic_buffer_t *term_manager_get_bvlogic_buffer(term_manager_t *manager) {
168 bvlogic_buffer_t *tmp;
169 node_table_t *nodes;
170
171 tmp = manager->bvlogic_buffer;
172 if (tmp == NULL) {
173 nodes = term_manager_get_nodes(manager);
174 tmp = (bvlogic_buffer_t *) safe_malloc(sizeof(bvlogic_buffer_t));
175 init_bvlogic_buffer(tmp, nodes);
176 manager->bvlogic_buffer = tmp;
177 }
178
179 return tmp;
180 }
181
term_manager_get_pp_buffer(term_manager_t * manager)182 pp_buffer_t *term_manager_get_pp_buffer(term_manager_t *manager) {
183 pp_buffer_t *tmp;
184
185 tmp = manager->pp_buffer;
186 if (tmp == NULL) {
187 tmp = (pp_buffer_t *) safe_malloc(sizeof(pp_buffer_t));
188 init_pp_buffer(tmp, 8);
189 manager->pp_buffer = tmp;
190 }
191
192 return tmp;
193 }
194
195
196 #if 0
197 /*
198 * Auxiliary buffer: reserved for internal use
199 */
200 static bvarith64_buffer_t *term_manager_get_bvarith64_aux_buffer(term_manager_t *manager) {
201 bvarith64_buffer_t *tmp;
202 object_store_t *mstore;
203
204 tmp = manager->bvarith64_aux_buffer;
205 if (tmp == NULL) {
206 mstore = term_manager_get_bvarith64_store(manager);
207 tmp = (bvarith64_buffer_t *) safe_malloc(sizeof(bvarith64_buffer_t));
208 init_bvarith64_buffer(tmp, manager->pprods, mstore);
209 manager->bvarith64_aux_buffer = tmp;
210 }
211
212 return tmp;
213 }
214 #endif
215
216 /*
217 * Delete all: free memory
218 */
term_manager_free_nodes(term_manager_t * manager)219 static void term_manager_free_nodes(term_manager_t *manager) {
220 node_table_t *tmp;
221
222 tmp = manager->nodes;
223 if (tmp != NULL) {
224 delete_node_table(tmp);
225 safe_free(tmp);
226 manager->nodes = NULL;
227 }
228 }
229
term_manager_free_bvarith_store(term_manager_t * manager)230 static void term_manager_free_bvarith_store(term_manager_t *manager) {
231 object_store_t *tmp;
232
233 tmp = manager->bvarith_store;
234 if (tmp != NULL) {
235 delete_bvmlist_store(tmp);
236 safe_free(tmp);
237 manager->bvarith_store = NULL;
238 }
239 }
240
term_manager_free_bvarith64_store(term_manager_t * manager)241 static void term_manager_free_bvarith64_store(term_manager_t *manager) {
242 object_store_t *tmp;
243
244 tmp = manager->bvarith64_store;
245 if (tmp != NULL) {
246 delete_bvmlist64_store(tmp);
247 safe_free(tmp);
248 manager->bvarith64_store = NULL;
249 }
250 }
251
term_manager_free_arith_buffer(term_manager_t * manager)252 static void term_manager_free_arith_buffer(term_manager_t *manager) {
253 rba_buffer_t *tmp;
254
255 tmp = manager->arith_buffer;
256 if (tmp != NULL) {
257 delete_rba_buffer(tmp);
258 safe_free(tmp);
259 manager->arith_buffer = NULL;
260 }
261 }
262
term_manager_free_bvarith_buffer(term_manager_t * manager)263 static void term_manager_free_bvarith_buffer(term_manager_t *manager) {
264 bvarith_buffer_t *tmp;
265
266 tmp = manager->bvarith_buffer;
267 if (tmp != NULL) {
268 delete_bvarith_buffer(tmp);
269 safe_free(tmp);
270 manager->bvarith_buffer = NULL;
271 }
272 }
273
term_manager_free_bvarith64_buffer(term_manager_t * manager)274 static void term_manager_free_bvarith64_buffer(term_manager_t *manager) {
275 bvarith64_buffer_t *tmp;
276
277 tmp = manager->bvarith64_buffer;
278 if (tmp != NULL) {
279 delete_bvarith64_buffer(tmp);
280 safe_free(tmp);
281 manager->bvarith64_buffer = NULL;
282 }
283 }
284
term_manager_free_bvlogic_buffer(term_manager_t * manager)285 static void term_manager_free_bvlogic_buffer(term_manager_t *manager) {
286 bvlogic_buffer_t *tmp;
287
288 tmp = manager->bvlogic_buffer;
289 if (tmp != NULL) {
290 delete_bvlogic_buffer(tmp);
291 safe_free(tmp);
292 manager->bvlogic_buffer = NULL;
293 }
294 }
295
term_manager_free_pp_buffer(term_manager_t * manager)296 static void term_manager_free_pp_buffer(term_manager_t *manager) {
297 pp_buffer_t *tmp;
298
299 tmp = manager->pp_buffer;
300 if (tmp != NULL) {
301 delete_pp_buffer(tmp);
302 safe_free(tmp);
303 manager->pp_buffer = NULL;
304 }
305 }
306
307 #if 0
308 static void term_manager_free_bvarith64_aux_buffer(term_manager_t *manager) {
309 bvarith64_buffer_t *tmp;
310
311 tmp = manager->bvarith64_aux_buffer;
312 if (tmp != NULL) {
313 delete_bvarith64_buffer(tmp);
314 safe_free(tmp);
315 manager->bvarith64_aux_buffer = NULL;
316 }
317 }
318 #endif
319
delete_term_manager(term_manager_t * manager)320 void delete_term_manager(term_manager_t *manager) {
321 term_manager_free_arith_buffer(manager);
322 term_manager_free_bvarith_buffer(manager);
323 term_manager_free_bvarith64_buffer(manager);
324 // term_manager_free_bvarith64_aux_buffer(manager); NEVER USED
325 term_manager_free_bvlogic_buffer(manager);
326 term_manager_free_pp_buffer(manager);
327
328 term_manager_free_bvarith_store(manager);
329 term_manager_free_bvarith64_store(manager);
330 term_manager_free_nodes(manager);
331
332 q_clear(&manager->r0);
333 delete_bvconstant(&manager->bv0);
334 delete_bvconstant(&manager->bv1);
335 delete_bvconstant(&manager->bv2);
336 delete_ivector(&manager->vector0);
337 }
338
339
340
341 /*
342 * Reset internal buffers and stores
343 */
reset_term_manager(term_manager_t * manager)344 void reset_term_manager(term_manager_t *manager) {
345 if (manager->arith_buffer != NULL) {
346 reset_rba_buffer(manager->arith_buffer);
347 }
348 if (manager->bvarith_buffer != NULL) {
349 reset_bvarith_buffer(manager->bvarith_buffer);
350 }
351 if (manager->bvarith64_buffer != NULL) {
352 reset_bvarith64_buffer(manager->bvarith64_buffer);
353 }
354 // if (manager->bvarith64_aux_buffer != NULL) {
355 // reset_bvarith64_buffer(manager->bvarith64_aux_buffer);
356 // }
357 if (manager->bvlogic_buffer != NULL) {
358 bvlogic_buffer_clear(manager->bvlogic_buffer);
359 }
360 if (manager->bvarith_store != NULL) {
361 reset_objstore(manager->bvarith_store);
362 }
363 if (manager->bvarith64_store != NULL) {
364 reset_objstore(manager->bvarith64_store);
365 }
366 if (manager->nodes != NULL) {
367 reset_node_table(manager->nodes);
368 }
369
370 q_clear(&manager->r0);
371 ivector_reset(&manager->vector0);
372 }
373
374
375
376
377 /************************************************
378 * CONVERSION OF ARRAYS OF BOOLEANS TO TERMS *
379 ***********************************************/
380
381 /*
382 * Check whether all elements of a are boolean constants
383 * - n = size of the array
384 */
bvarray_is_constant(const term_t * a,uint32_t n)385 static bool bvarray_is_constant(const term_t *a, uint32_t n) {
386 uint32_t i;
387
388 for (i=0; i<n; i++) {
389 if (index_of(a[i]) != bool_const) return false;
390 assert(a[i] == true_term || a[i] == false_term);
391 }
392
393 return true;
394 }
395
396
397 /*
398 * Convert a to a 64bit value (padded with 0)
399 */
bvarray_get_constant64(const term_t * a,uint32_t n)400 static uint64_t bvarray_get_constant64(const term_t *a, uint32_t n) {
401 uint64_t c;
402
403 assert(n <= 64);
404 c = 0;
405 while (n > 0) {
406 n --;
407 assert(a[n] == true_term || a[n] == false_term);
408 c = (c << 1) | (uint64_t) (1 ^ polarity_of(a[n]));
409 }
410
411 return c;
412 }
413
414
415 /*
416 * Copy constant array into c
417 */
bvarray_get_constant(const term_t * a,uint32_t n,bvconstant_t * c)418 static void bvarray_get_constant(const term_t *a, uint32_t n, bvconstant_t *c) {
419 uint32_t i, k;
420
421 assert(n > 64);
422 k = (n + 31) >> 5;
423 bvconstant_set_bitsize(c, n);
424
425 bvconst_clear(c->data, k);
426 for (i=0; i<n; i++) {
427 assert(a[i] == true_term || a[i] == false_term);
428 if (a[i] == true_term) {
429 bvconst_set_bit(c->data, i);
430 }
431 }
432 }
433
434
435 /*
436 * Check whether term b is (bit i x)
437 */
term_is_bit_i(term_table_t * tbl,term_t b,uint32_t i,term_t x)438 static bool term_is_bit_i(term_table_t *tbl, term_t b, uint32_t i, term_t x) {
439 select_term_t *s;
440
441 if (is_pos_term(b) && term_kind(tbl, b) == BIT_TERM) {
442 s = bit_term_desc(tbl, b);
443 return s->idx == i && s->arg == x;
444 }
445
446 return false;
447 }
448
449
450 /*
451 * Check whether b is (bit 0 x) for some x
452 * if so return x, otherwise return NULL_TERM
453 */
term_is_bit0(term_table_t * tbl,term_t b)454 static term_t term_is_bit0(term_table_t *tbl, term_t b) {
455 select_term_t *s;
456
457 if (is_pos_term(b) && term_kind(tbl, b) == BIT_TERM) {
458 s = bit_term_desc(tbl, b);
459 if (s->idx == 0) {
460 return s->arg;
461 }
462 }
463
464 return NULL_TERM;
465 }
466
467 /*
468 * Convert abstraction sign to a term
469 * - return NULL_TERM is sign is undef
470 */
abs64sign_to_term(int32_t sign)471 static term_t abs64sign_to_term(int32_t sign) {
472 term_t t;
473
474 t = NULL_TERM;
475 if (sign == sign_zero) {
476 t = false_term;
477 } else if (sign == sign_one) {
478 t = true_term;
479 } else if (sign != sign_undef) {
480 // sign is a Boolean term
481 t = sign;
482 }
483
484 return t;
485 }
486
487 /*
488 * Check whether a is equal to an existing term x
489 * - if so return x
490 * - otherwise return NULL_TERM
491 *
492 * This checks whether a[0] ... a[n-1] are of the form
493 * (bit 0 x) (bit 1 x) ... (bit n-1 x),
494 * where x is a term of n bits.
495 */
bvarray_get_var(term_table_t * tbl,const term_t * a,uint32_t n)496 static term_t bvarray_get_var(term_table_t *tbl, const term_t *a, uint32_t n) {
497 bv64_abs_t abs;
498 term_t x, s;
499 uint32_t i, m;
500
501 assert(n > 0);
502
503 x = term_is_bit0(tbl, a[0]);
504 if (x == NULL_TERM || term_bitsize(tbl, x) != n) {
505 return NULL_TERM;
506 }
507
508 if (n <= 64) {
509 // use abstraction to learn sign + number of significant bits
510 bv64_abstract_term(tbl, x, &abs);
511 assert(0 < abs.nbits && abs.nbits <= n);
512 m = abs.nbits - 1;
513 for (i=1; i<m; i++) {
514 if (! term_is_bit_i(tbl, a[i], i, x)) {
515 return NULL_TERM;
516 }
517 }
518
519 // check whether the a[i+1, .., n-1] contain the sign bit of x
520 s = abs64sign_to_term(abs.sign);
521 if (s != NULL_TERM) {
522 // the sign bit is s
523 while (i<n) {
524 if (a[i] != s) {
525 return NULL_TERM;
526 }
527 i ++;
528 }
529 } else {
530 // the sign bit is (select x m)
531 while (i<n) {
532 if (! term_is_bit_i(tbl, a[i], m, x)) {
533 return NULL_TERM;
534 }
535 i ++;
536 }
537 }
538 } else {
539 // Interval abstraction not implemented for n>64
540 for (i=1; i<n; i++) {
541 if (! term_is_bit_i(tbl, a[i], i, x)) {
542 return NULL_TERM;
543 }
544 }
545 }
546
547
548 return x;
549 }
550
551 /*
552 * Convert array a to a term
553 * - side effect: use bv0
554 */
bvarray_get_term(term_manager_t * manager,const term_t * a,uint32_t n)555 static term_t bvarray_get_term(term_manager_t *manager, const term_t *a, uint32_t n) {
556 term_table_t *terms;
557 bvconstant_t *bv;
558 term_t t;
559
560 assert(n > 0);
561
562 terms = manager->terms;
563
564 if (bvarray_is_constant(a, n)) {
565 if (n <= 64) {
566 t = bv64_constant(terms, n, bvarray_get_constant64(a, n));
567 } else {
568 bv = &manager->bv0;
569 bvarray_get_constant(a, n, bv);
570 assert(bv->bitsize == n);
571 t = bvconst_term(terms, n, bv->data);
572 }
573 } else {
574 // try to convert to an existing t
575 t = bvarray_get_var(terms, a, n);
576 if (t == NULL_TERM) {
577 t = bvarray_term(terms, n, a);
578 }
579 }
580
581 return t;
582 }
583
584
585
586 /*
587 * BITVECTORS OF SIZE 1
588 */
589
590 /*
591 * Check whether x is equivalent to (bveq a 0b0) or (bveq a 0b1) where a is a term
592 * of type (bitvector 1).
593 * - if x is (bveq a 0b0): return a and set polarity to false
594 * - if x is (bveq a 0b1): return a and set polarity to true
595 * - if x is (not (bveq a 0b0)): return a and set polarity to true
596 * - if x is (not (bveq a 0b1)): return a and set polarity to false
597 * - otherwise, return NULL_TERM (leave polarity unchanged)
598 */
term_is_bveq1(term_table_t * tbl,term_t x,bool * polarity)599 static term_t term_is_bveq1(term_table_t *tbl, term_t x, bool *polarity) {
600 composite_term_t *eq;
601 bvconst64_term_t *c;
602 term_t a, b;
603
604 if (term_kind(tbl, x) == BV_EQ_ATOM) {
605 eq = bveq_atom_desc(tbl, x);
606 a = eq->arg[0];
607 b = eq->arg[1];
608 if (term_bitsize(tbl, a) == 1) {
609 assert(term_bitsize(tbl, b) == 1);
610 if (term_kind(tbl, a) == BV64_CONSTANT) {
611 // a is either 0b0 or 0b1
612 c = bvconst64_term_desc(tbl, a);
613 assert(c->value == 0 || c->value == 1);
614 *polarity = ((bool) c->value) ^ is_neg_term(x);
615 return b;
616 }
617
618 if (term_kind(tbl, b) == BV64_CONSTANT) {
619 // b is either 0b0 or 0b1
620 c = bvconst64_term_desc(tbl, b);
621 assert(c->value == 0 || c->value == 1);
622 *polarity = ((bool) c->value) ^ is_neg_term(x);
623 return a;
624 }
625 }
626 }
627
628 return NULL_TERM;
629 }
630
631
632 /*
633 * Rewrite (bveq [p] [q]) to (eq p q)
634 * - t1 and t2 are both bv-arrays of one bit
635 * - this is called after checking for simplification (so
636 * we known that (p == q) does not simplify to a single term).
637 */
mk_bveq_arrays1(term_manager_t * manager,term_t t1,term_t t2)638 static term_t mk_bveq_arrays1(term_manager_t *manager, term_t t1, term_t t2) {
639 composite_term_t *a;
640 composite_term_t *b;
641
642 a = bvarray_term_desc(manager->terms, t1);
643 b = bvarray_term_desc(manager->terms, t2);
644
645 assert(a->arity == 1 && b->arity == 1);
646 return mk_iff(manager, a->arg[0], b->arg[0]);
647 }
648
649
650 /*
651 * Auxiliary function: build (bveq t1 t2)
652 * - try to simplify to true or false
653 * - attempt to simplify the equality if it's between bit-arrays or bit-arrays and constant
654 * - build an atom if no simplification works
655 */
mk_bitvector_eq(term_manager_t * manager,term_t t1,term_t t2)656 static term_t mk_bitvector_eq(term_manager_t *manager, term_t t1, term_t t2) {
657 term_table_t *tbl;
658 term_t aux;
659
660 tbl = manager->terms;
661
662 if (t1 == t2) return true_term;
663 if (disequal_bitvector_terms(tbl, t1, t2)) {
664 return false_term;
665 }
666
667 /*
668 * Try simplifications. We know that t1 and t2 are not both constant
669 * (because disequal_bitvector_terms returned false).
670 */
671 if (manager->simplify_bveq1) {
672 aux = simplify_bveq(tbl, t1, t2);
673 if (aux != NULL_TERM) {
674 // Simplification worked
675 return aux;
676 }
677 }
678 /*
679 * Special case: for bit-vector of size 1
680 * - convert to boolean equality
681 */
682 if (manager->simplify_bveq1 && term_bitsize(tbl, t1) == 1 &&
683 term_kind(tbl, t1) == BV_ARRAY && term_kind(tbl, t2) == BV_ARRAY) {
684 assert(term_bitsize(tbl, t2) == 1);
685 return mk_bveq_arrays1(manager, t1, t2);
686 }
687
688 /*
689 * Default: normalize then build a bveq_atom
690 */
691 if (t1 > t2) {
692 aux = t1; t1 = t2; t2 = aux;
693 }
694
695 return bveq_atom(tbl, t1, t2);
696 }
697
698
699
700 /*
701 * Special constructor for (iff x y) when x or y (or both)
702 * are equivalent to (bveq a 0b0) or (bveq a 0b1).
703 *
704 * Try the following rewrite rules:
705 * iff (bveq a 0b0) (bveq b 0b0) ---> (bveq a b)
706 * iff (bveq a 0b0) (bveq b 0b1) ---> (not (bveq a b))
707 * iff (bveq a 0b1) (bveq b 0b0) ---> (not (bveq a b))
708 * iff (bveq a 0b1) (bveq b 0b1) ---> (bveq a b)
709 *
710 * iff (bveq a 0b0) y ---> (not (bveq a (bvarray y)))
711 * iff (bveq a 0b1) y ---> (bveq a (bvarray y))
712 *
713 * return NULL_TERM if none of these rules can be applied
714 */
try_iff_bveq_simplification(term_manager_t * manager,term_t x,term_t y)715 static term_t try_iff_bveq_simplification(term_manager_t *manager, term_t x, term_t y) {
716 term_table_t *tbl;
717 term_t a, b, t;
718 bool pa, pb;
719
720 pa = false;
721 pb = false; // to prevent GCC warning
722
723 tbl = manager->terms;
724
725 a = term_is_bveq1(tbl, x, &pa);
726 b = term_is_bveq1(tbl, y, &pb);
727 if (a != NULL_TERM || b != NULL_TERM) {
728 if (a != NULL_TERM && b != NULL_TERM) {
729 /*
730 * x is (bveq a <constant>)
731 * y is (bveq b <constant>)
732 */
733 t = mk_bitvector_eq(manager, a, b);
734 t = signed_term(t, (pa == pb));
735 return t;
736 }
737
738 if (a != NULL_TERM) {
739 /*
740 * x is (bveq a <constant>):
741 * if pa is true:
742 * (iff (bveq a 0b1) y) --> (bveq a (bvarray y))
743 * if pa is false:
744 * (iff (bveq a 0b0) y) --> (not (bveq a (bvarray y)))
745 *
746 * TODO? We could rewrite to (bveq a (bvarray ~y))??
747 */
748 t = bvarray_get_term(manager, &y, 1);
749 t = mk_bitvector_eq(manager, a, t);
750 t = signed_term(t, pa);
751 return t;
752 }
753
754 if (b != NULL_TERM) {
755 /*
756 * y is (bveq b <constant>)
757 */
758 t = bvarray_get_term(manager, &x, 1);
759 t = mk_bitvector_eq(manager, b, t);
760 t = signed_term(t, pb);
761 return t;
762 }
763 }
764
765 return NULL_TERM;
766 }
767
768
769
770
771 /**********************
772 * ARITHMETIC TERMS *
773 *********************/
774
775 /*
776 * Arithmetic constant (rational)
777 * - r must be normalized
778 */
mk_arith_constant(term_manager_t * manager,rational_t * r)779 term_t mk_arith_constant(term_manager_t *manager, rational_t *r) {
780 return arith_constant(manager->terms, r);
781 }
782
783
784 /*
785 * Convert b to an arithmetic term:
786 * - b->ptbl must be equal to manager->pprods
787 * - b may be the same as manager->arith_buffer
788 * - side effect: b is reset
789 *
790 * Simplifications (after normalization)
791 * - if b is a constant then a constant rational is created
792 * - if b is of the form 1. t then t is returned
793 * - if b is of the from 1. t_1^d_1 ... t_n^d_n then a power product is returned
794 * - otherwise a polynomial term is created
795 */
arith_buffer_to_term(term_table_t * tbl,rba_buffer_t * b)796 static term_t arith_buffer_to_term(term_table_t *tbl, rba_buffer_t *b) {
797 mono_t *m;
798 pprod_t *r;
799 uint32_t n;
800 term_t t;
801
802 assert(b->ptbl == tbl->pprods);
803
804 n = b->nterms;
805 if (n == 0) {
806 t = zero_term;
807 } else if (n == 1) {
808 m = rba_buffer_root_mono(b); // unique monomial of b
809 r = m->prod;
810 if (r == empty_pp) {
811 // constant polynomial
812 t = arith_constant(tbl, &m->coeff);
813 } else if (q_is_one(&m->coeff)) {
814 // term or power product
815 t = pp_is_var(r) ? var_of_pp(r) : pprod_term(tbl, r);
816 } else {
817 // can't simplify
818 t = arith_poly(tbl, b);
819 }
820 } else {
821 t = arith_poly(tbl, b);
822 }
823
824 reset_rba_buffer(b);
825
826 return t;
827 }
828
829
mk_arith_term(term_manager_t * manager,rba_buffer_t * b)830 term_t mk_arith_term(term_manager_t *manager, rba_buffer_t *b) {
831 return arith_buffer_to_term(manager->terms, b);
832 }
833
mk_direct_arith_term(term_table_t * tbl,rba_buffer_t * b)834 term_t mk_direct_arith_term(term_table_t *tbl, rba_buffer_t *b) {
835 return arith_buffer_to_term(tbl, b);
836 }
837
838
839
840 /*********************************
841 * BOOLEAN-TERM CONSTRUCTORS *
842 ********************************/
843
844 /*
845 * Simplifications:
846 * x or x --> x
847 * x or true --> true
848 * x or false --> x
849 * x or (not x) --> true
850 *
851 * Normalization: put smaller index first
852 */
mk_binary_or(term_manager_t * manager,term_t x,term_t y)853 term_t mk_binary_or(term_manager_t *manager, term_t x, term_t y) {
854 term_t aux[2];
855
856 if (x == y) return x;
857 if (x == true_term) return x;
858 if (y == true_term) return y;
859 if (x == false_term) return y;
860 if (y == false_term) return x;
861 if (opposite_bool_terms(x, y)) return true_term;
862
863 if (x < y) {
864 aux[0] = x; aux[1] = y;
865 } else {
866 aux[0] = y; aux[1] = x;
867 }
868
869 return or_term(manager->terms, 2, aux);
870 }
871
872
873 /*
874 * Rewrite (and x y) to (not (or (not x) (not y)))
875 */
mk_binary_and(term_manager_t * manager,term_t x,term_t y)876 term_t mk_binary_and(term_manager_t *manager, term_t x, term_t y) {
877 return opposite_term(mk_binary_or(manager, opposite_term(x), opposite_term(y)));
878 }
879
880
881 /*
882 * Rewrite (implies x y) to (or (not x) y)
883 */
mk_implies(term_manager_t * manager,term_t x,term_t y)884 term_t mk_implies(term_manager_t *manager, term_t x, term_t y) {
885 return mk_binary_or(manager, opposite_term(x), y);
886 }
887
888
889 /*
890 * Check whether x is uninterpreted or the negation of an uninterpreted boolean term
891 */
is_literal(term_manager_t * manager,term_t x)892 static inline bool is_literal(term_manager_t *manager, term_t x) {
893 return kind_for_idx(manager->terms, index_of(x)) == UNINTERPRETED_TERM;
894 }
895
896
897 /*
898 * Simplifications:
899 * iff x x --> true
900 * iff x true --> x
901 * iff x false --> not x
902 * iff x (not x) --> false
903 *
904 * iff (not x) (not y) --> eq x y
905 *
906 * Optional simplification:
907 * iff (not x) y --> not (eq x y) (NOT USED ANYMORE)
908 *
909 * Smaller index is on the left-hand-side of eq
910 */
mk_iff(term_manager_t * manager,term_t x,term_t y)911 term_t mk_iff(term_manager_t *manager, term_t x, term_t y) {
912 term_t aux;
913
914 if (x == y) return true_term;
915 if (x == true_term) return y;
916 if (y == true_term) return x;
917 if (x == false_term) return opposite_term(y);
918 if (y == false_term) return opposite_term(x);
919 if (opposite_bool_terms(x, y)) return false_term;
920
921 /*
922 * Try iff/bveq simplifications.
923 */
924 aux = try_iff_bveq_simplification(manager, x, y);
925 if (aux != NULL_TERM) {
926 return aux;
927 }
928
929 /*
930 * swap if x > y
931 */
932 if (x > y) {
933 aux = x; x = y; y = aux;
934 }
935
936 /*
937 * - rewrite (iff (not x) (not y)) to (eq x y)
938 * - rewrite (iff (not x) y) to (eq x (not y))
939 * unless y is uninterpreted and x is not
940 */
941 if (is_neg_term(x) &&
942 (is_neg_term(y) || is_literal(manager, x) || !is_literal(manager, y))) {
943 x = opposite_term(x);
944 y = opposite_term(y);
945 }
946
947 return eq_term(manager->terms, x, y);
948 }
949
950
951 /*
952 * Rewrite (xor x y) to (not (iff x y))
953 *
954 * NOTE: used to be (xor x y) to (iff (not x) y)
955 */
mk_binary_xor(term_manager_t * manager,term_t x,term_t y)956 term_t mk_binary_xor(term_manager_t *manager, term_t x, term_t y) {
957 return opposite_term(mk_iff(manager, x, y));
958 }
959
960
961
962
963 /*
964 * N-ARY OR/AND
965 */
966
967 /*
968 * Construct (or a[0] ... a[n-1])
969 * - all terms are assumed valid and boolean
970 * - array a is modified (sorted)
971 * - n must be positive
972 */
mk_or(term_manager_t * manager,uint32_t n,term_t * a)973 term_t mk_or(term_manager_t *manager, uint32_t n, term_t *a) {
974 uint32_t i, j;
975 term_t x, y;
976
977 /*
978 * Sorting the terms ensure:
979 * - true_term shows up first if it's present in a
980 * then false_term if it's present
981 * then all the other boolean terms.
982 * - if x and (not x) are both in a, then they occur
983 * at successive positions in a after sorting.
984 */
985 assert(n > 0);
986 int_array_sort(a, n);
987
988 x = a[0];
989 if (x == true_term) {
990 return true_term;
991 }
992
993 j = 0;
994 if (x != false_term) {
995 // a[j] = x; NOT NECESSARY
996 j ++;
997 }
998
999 // remove duplicates and check for x/not x in succession
1000 for (i=1; i<n; i++) {
1001 y = a[i];
1002 if (x != y) {
1003 if (y == opposite_term(x)) {
1004 return true_term;
1005 }
1006 assert(y != false_term && y != true_term);
1007 x = y;
1008 a[j] = x;
1009 j ++;
1010 }
1011 }
1012
1013 if (j <= 1) {
1014 // if j = 0, then x = false_term and all elements of a are false
1015 // if j = 1, then x is the unique non-false term in a
1016 return x;
1017 } else {
1018 return or_term(manager->terms, j, a);
1019 }
1020 }
1021
1022
1023 /*
1024 * Construct (and a[0] ... a[n-1])
1025 * - n must be positive
1026 * - a is modified
1027 */
mk_and(term_manager_t * manager,uint32_t n,term_t * a)1028 term_t mk_and(term_manager_t *manager, uint32_t n, term_t *a) {
1029 uint32_t i;
1030
1031 for (i=0; i<n; i++) {
1032 a[i] = opposite_term(a[i]);
1033 }
1034
1035 return opposite_term(mk_or(manager, n, a));
1036 }
1037
1038
1039
1040
1041
1042 /*
1043 * N-ARY XOR
1044 */
1045
1046 /*
1047 * Construct (xor a[0] ... a[n-1])
1048 * - n must be positive
1049 * - all terms in a must be valid and boolean
1050 * - a is modified
1051 */
mk_xor(term_manager_t * manager,uint32_t n,term_t * a)1052 term_t mk_xor(term_manager_t *manager, uint32_t n, term_t *a) {
1053 uint32_t i, j;
1054 term_t x, y;
1055 bool negate;
1056
1057
1058 /*
1059 * First pass: remove true_term/false_term and
1060 * replace negative terms by their opposite
1061 */
1062 negate = false;
1063 j = 0;
1064 for (i=0; i<n; i++) {
1065 x = a[i];
1066 if (index_of(x) == bool_const) {
1067 assert(x == true_term || x == false_term);
1068 negate ^= is_pos_term(x); // flip sign if x is true
1069 } else {
1070 assert(x != true_term && x != false_term);
1071 // apply rule (xor ... (not x) ...) = (not (xor ... x ...))
1072 negate ^= is_neg_term(x); // flip sign for (not x)
1073 x = unsigned_term(x); // turn (not x) into x
1074 a[j] = x;
1075 j ++;
1076 }
1077 }
1078
1079 /*
1080 * Second pass: remove duplicates (i.e., apply the rule (xor x x) --> false
1081 */
1082 n = j;
1083 int_array_sort(a, n);
1084 j = 0;
1085 i = 0;
1086 while (i+1 < n) {
1087 x = a[i];
1088 if (x == a[i+1]) {
1089 i += 2;
1090 } else {
1091 a[j] = x;
1092 j ++;
1093 i ++;
1094 }
1095 }
1096 assert(i == n || i + 1 == n);
1097 if (i+1 == n) {
1098 a[j] = a[i];
1099 j ++;
1100 }
1101
1102
1103 /*
1104 * Build the result: (xor negate (xor a[0] ... a[j-1]))
1105 */
1106 if (j == 0) {
1107 return bool2term(negate);
1108 }
1109
1110 if (j == 1) {
1111 return negate ^ a[0];
1112 }
1113
1114 if (j == 2) {
1115 x = a[0];
1116 y = a[1];
1117 assert(is_pos_term(x) && is_pos_term(y) && x < y);
1118 if (negate) {
1119 /*
1120 * to be consistent with mk_iff:
1121 * not (xor x y) --> (eq (not x) y) if y is uninterpreted and x is not
1122 * not (xor x y) --> (eq x (not y)) otherwise
1123 */
1124 if (is_literal(manager, y) && !is_literal(manager, x)) {
1125 x = opposite_term(x);
1126 } else {
1127 y = opposite_term(y);
1128 }
1129 }
1130 return opposite_term(eq_term(manager->terms, x, y));
1131 }
1132
1133 // general case: j >= 3
1134 x = xor_term(manager->terms, j, a);
1135 if (negate) {
1136 x = opposite_term(x);
1137 }
1138
1139 return x;
1140 }
1141
1142
1143 /*
1144 * Safe versions of mk_or, mk_and, mk_xor: make a copy of the argument array
1145 * into manager->vector0
1146 */
mk_or_safe(term_manager_t * manager,uint32_t n,const term_t a[])1147 term_t mk_or_safe(term_manager_t *manager, uint32_t n, const term_t a[]) {
1148 ivector_t *v;
1149
1150 v = &manager->vector0;
1151 ivector_copy(v, a, n);
1152 assert(v->size == n);
1153 return mk_or(manager, n, v->data);
1154 }
1155
mk_and_safe(term_manager_t * manager,uint32_t n,const term_t a[])1156 term_t mk_and_safe(term_manager_t *manager, uint32_t n, const term_t a[]) {
1157 ivector_t *v;
1158
1159 v = &manager->vector0;
1160 ivector_copy(v, a, n);
1161 assert(v->size == n);
1162 return mk_and(manager, n, v->data);
1163 }
1164
mk_xor_safe(term_manager_t * manager,uint32_t n,const term_t a[])1165 term_t mk_xor_safe(term_manager_t *manager, uint32_t n, const term_t a[]) {
1166 ivector_t *v;
1167
1168 v = &manager->vector0;
1169 ivector_copy(v, a, n);
1170 assert(v->size == n);
1171 return mk_xor(manager, n, v->data);
1172 }
1173
1174
1175 /******************
1176 * IF-THEN-ELSE *
1177 *****************/
1178
1179 /*
1180 * BIT-VECTOR IF-THEN-ELSE
1181 */
1182
1183 /*
1184 * Build (ite c x y) when both x and y are boolean constants.
1185 */
const_ite_simplify(term_t c,term_t x,term_t y)1186 static term_t const_ite_simplify(term_t c, term_t x, term_t y) {
1187 assert(x == true_term || x == false_term);
1188 assert(y == true_term || y == false_term);
1189
1190 if (x == y) return x;
1191 if (x == true_term) {
1192 assert(y == false_term);
1193 return c;
1194 }
1195
1196 assert(x == false_term && y == true_term);
1197 return opposite_term(c);
1198 }
1199
1200
1201 /*
1202 * Convert (ite c u v) into a bvarray term:
1203 * - c is a boolean
1204 * - u and v are two bv64 constants
1205 */
mk_bvconst64_ite(term_manager_t * manager,term_t c,bvconst64_term_t * u,bvconst64_term_t * v)1206 static term_t mk_bvconst64_ite(term_manager_t *manager, term_t c, bvconst64_term_t *u, bvconst64_term_t *v) {
1207 uint32_t i, n;
1208 term_t bu, bv;
1209 term_t *a;
1210
1211 n = u->bitsize;
1212 assert(v->bitsize == n);
1213 resize_ivector(&manager->vector0, n);
1214 a = manager->vector0.data;
1215
1216 for (i=0; i<n; i++) {
1217 bu = bool2term(tst_bit64(u->value, i)); // bit i of u
1218 bv = bool2term(tst_bit64(v->value, i)); // bit i of v
1219
1220 a[i] = const_ite_simplify(c, bu, bv); // a[i] = (ite c bu bv)
1221 }
1222
1223 return bvarray_get_term(manager, a, n);
1224 }
1225
1226
1227 /*
1228 * Same thing with u and v two generic bv constants
1229 */
mk_bvconst_ite(term_manager_t * manager,term_t c,bvconst_term_t * u,bvconst_term_t * v)1230 static term_t mk_bvconst_ite(term_manager_t *manager, term_t c, bvconst_term_t *u, bvconst_term_t *v) {
1231 uint32_t i, n;
1232 term_t bu, bv;
1233 term_t *a;
1234
1235 n = u->bitsize;
1236 assert(v->bitsize == n);
1237 resize_ivector(&manager->vector0, n);
1238 a = manager->vector0.data;
1239
1240 for (i=0; i<n; i++) {
1241 bu = bool2term(bvconst_tst_bit(u->data, i));
1242 bv = bool2term(bvconst_tst_bit(v->data, i));
1243
1244 a[i] = const_ite_simplify(c, bu, bv);
1245 }
1246
1247 return bvarray_get_term(manager, a, n);
1248 }
1249
1250
1251
1252 /*
1253 * Given three boolean terms c, x, and y, check whether (ite c x y)
1254 * simplifies and if so return the result.
1255 * - return NULL_TERM if no simplification is found.
1256 * - the function assumes c is not a boolean constant
1257 */
check_ite_simplifies(term_t c,term_t x,term_t y)1258 static term_t check_ite_simplifies(term_t c, term_t x, term_t y) {
1259 assert(c != true_term && c != false_term);
1260
1261 // (ite c x y) --> (ite c true y) if c == x
1262 // (ite c x y) --> (ite c false y) if c == not x
1263 if (c == x) {
1264 x = true_term;
1265 } else if (opposite_bool_terms(c, x)) {
1266 x = false_term;
1267 }
1268
1269 // (ite c x y) --> (ite c x false) if c == y
1270 // (ite c x y) --> (ite c x true) if c == not y
1271 if (c == y) {
1272 y = false_term;
1273 } else if (opposite_bool_terms(c, y)) {
1274 y = true_term;
1275 }
1276
1277 // (ite c x x) --> x
1278 // (ite c true false) --> c
1279 // (ite c false true) --> not c
1280 if (x == y) return x;
1281 if (x == true_term && y == false_term) return c;
1282 if (x == false_term && y == true_term) return opposite_term(c);
1283
1284 return NULL_TERM;
1285 }
1286
1287
1288 /*
1289 * Attempt to convert (ite c u v) into a bvarray term:
1290 * - u is a bitvector constant of no more than 64 bits
1291 * - v is a bvarray term
1292 * Return NULL_TERM if the simplifications fail.
1293 */
check_ite_bvconst64(term_manager_t * manager,term_t c,bvconst64_term_t * u,composite_term_t * v)1294 static term_t check_ite_bvconst64(term_manager_t *manager, term_t c, bvconst64_term_t *u, composite_term_t *v) {
1295 uint32_t i, n;
1296 term_t b;
1297 term_t *a;
1298
1299 n = u->bitsize;
1300 assert(n == v->arity);
1301 resize_ivector(&manager->vector0, n);
1302 a = manager->vector0.data;
1303
1304 for (i=0; i<n; i++) {
1305 b = bool2term(tst_bit64(u->value, i)); // bit i of u
1306 b = check_ite_simplifies(c, b, v->arg[i]);
1307
1308 if (b == NULL_TERM) {
1309 return NULL_TERM;
1310 }
1311 a[i] = b;
1312 }
1313
1314 return bvarray_get_term(manager, a, n);
1315 }
1316
1317
1318 /*
1319 * Same thing for a generic constant u
1320 */
check_ite_bvconst(term_manager_t * manager,term_t c,bvconst_term_t * u,composite_term_t * v)1321 static term_t check_ite_bvconst(term_manager_t *manager, term_t c, bvconst_term_t *u, composite_term_t *v) {
1322 uint32_t i, n;
1323 term_t b;
1324 term_t *a;
1325
1326 n = u->bitsize;
1327 assert(n == v->arity);
1328 resize_ivector(&manager->vector0, n);
1329 a = manager->vector0.data;
1330
1331 for (i=0; i<n; i++) {
1332 b = bool2term(bvconst_tst_bit(u->data, i)); // bit i of u
1333 b = check_ite_simplifies(c, b, v->arg[i]);
1334
1335 if (b == NULL_TERM) {
1336 return NULL_TERM;
1337 }
1338 a[i] = b;
1339 }
1340
1341 return bvarray_get_term(manager, a, n);
1342 }
1343
1344
1345 /*
1346 * Same thing when both u and v are bvarray terms.
1347 */
check_ite_bvarray(term_manager_t * manager,term_t c,composite_term_t * u,composite_term_t * v)1348 static term_t check_ite_bvarray(term_manager_t *manager, term_t c, composite_term_t *u, composite_term_t *v) {
1349 uint32_t i, n;
1350 term_t b;
1351 term_t *a;
1352
1353 n = u->arity;
1354 assert(n == v->arity);
1355 resize_ivector(&manager->vector0, n);
1356 a = manager->vector0.data;
1357
1358 for (i=0; i<n; i++) {
1359 b = check_ite_simplifies(c, u->arg[i], v->arg[i]);
1360
1361 if (b == NULL_TERM) {
1362 return NULL_TERM;
1363 }
1364 a[i] = b;
1365 }
1366
1367 return bvarray_get_term(manager, a, n);
1368 }
1369
1370
1371
1372 /*
1373 * Build (ite c x y) c is boolean, x and y are bitvector terms
1374 * Use vector0 as a buffer.
1375 */
mk_bv_ite(term_manager_t * manager,term_t c,term_t x,term_t y)1376 term_t mk_bv_ite(term_manager_t *manager, term_t c, term_t x, term_t y) {
1377 term_table_t *tbl;
1378 term_kind_t kind_x, kind_y;
1379 term_t aux;
1380
1381 tbl = manager->terms;
1382
1383 assert(term_type(tbl, x) == term_type(tbl, y) &&
1384 is_bitvector_term(tbl, x) &&
1385 is_boolean_term(tbl, c));
1386
1387 // Try generic simplification first
1388 if (x == y) return x;
1389 if (c == true_term) return x;
1390 if (c == false_term) return y;
1391
1392 // Check whether (ite c x y) simplifies to a bv_array term
1393 kind_x = term_kind(tbl, x);
1394 kind_y = term_kind(tbl, y);
1395 aux = NULL_TERM;
1396 switch (kind_x) {
1397 case BV64_CONSTANT:
1398 assert(kind_y != BV_CONSTANT);
1399 if (kind_y == BV64_CONSTANT) {
1400 return mk_bvconst64_ite(manager, c, bvconst64_term_desc(tbl, x), bvconst64_term_desc(tbl, y));
1401 }
1402 if (kind_y == BV_ARRAY) {
1403 aux = check_ite_bvconst64(manager, c, bvconst64_term_desc(tbl, x), bvarray_term_desc(tbl, y));
1404 }
1405 break;
1406
1407 case BV_CONSTANT:
1408 assert(kind_y != BV64_CONSTANT);
1409 if (kind_y == BV_CONSTANT) {
1410 return mk_bvconst_ite(manager, c, bvconst_term_desc(tbl, x), bvconst_term_desc(tbl, y));
1411 }
1412 if (kind_y == BV_ARRAY) {
1413 aux = check_ite_bvconst(manager, c, bvconst_term_desc(tbl, x), bvarray_term_desc(tbl, y));
1414 }
1415 break;
1416
1417 case BV_ARRAY:
1418 if (kind_y == BV64_CONSTANT) {
1419 aux = check_ite_bvconst64(manager, opposite_term(c), bvconst64_term_desc(tbl, y), bvarray_term_desc(tbl, x));
1420 } else if (kind_y == BV_CONSTANT) {
1421 aux = check_ite_bvconst(manager, opposite_term(c), bvconst_term_desc(tbl, y), bvarray_term_desc(tbl, x));
1422 } else if (kind_y == BV_ARRAY) {
1423 aux = check_ite_bvarray(manager, opposite_term(c), bvarray_term_desc(tbl, y), bvarray_term_desc(tbl, x));
1424 }
1425 break;
1426
1427 default:
1428 break;
1429 }
1430
1431 if (aux != NULL_TERM) {
1432 return aux;
1433 }
1434
1435 /*
1436 * No simplification found: build a standard ite.
1437 * Normalize first: (ite (not c) x y) --> (ite c y x)
1438 */
1439 if (is_neg_term(c)) {
1440 c = opposite_term(c);
1441 aux = x; x = y; y = aux;
1442 }
1443
1444 return ite_term(tbl, term_type(tbl, x), c, x, y);
1445 }
1446
1447
1448
1449
1450
1451 /*
1452 * BOOLEAN IF-THEN-ELSE
1453 */
1454
1455 /*
1456 * Build (bv-eq x (ite c y z))
1457 * - c not true/false
1458 */
mk_bveq_ite(term_manager_t * manager,term_t c,term_t x,term_t y,term_t z)1459 static term_t mk_bveq_ite(term_manager_t *manager, term_t c, term_t x, term_t y, term_t z) {
1460 term_t ite, aux;
1461
1462 assert(term_type(manager->terms, x) == term_type(manager->terms, y) &&
1463 term_type(manager->terms, x) == term_type(manager->terms, z));
1464
1465 ite = mk_bv_ite(manager, c, y, z);
1466
1467 // normalize (bveq x ite): put smaller index on the left
1468 if (x > ite) {
1469 aux = x; x = ite; ite = aux;
1470 }
1471
1472 return bveq_atom(manager->terms, x, ite);
1473 }
1474
1475
1476 /*
1477 * Special constructor for (ite c (bveq x y) (bveq z u))
1478 *
1479 * Apply lift-if rule:
1480 * (ite c (bveq x y) (bveq x u)) ---> (bveq x (ite c y u))
1481 */
mk_lifted_ite_bveq(term_manager_t * manager,term_t c,term_t t,term_t e)1482 static term_t mk_lifted_ite_bveq(term_manager_t *manager, term_t c, term_t t, term_t e) {
1483 term_table_t *tbl;
1484 composite_term_t *eq1, *eq2;
1485 term_t x;
1486
1487 tbl = manager->terms;
1488
1489 assert(is_pos_term(t) && is_pos_term(e) &&
1490 term_kind(tbl, t) == BV_EQ_ATOM && term_kind(tbl, e) == BV_EQ_ATOM);
1491
1492 eq1 = composite_for_idx(tbl, index_of(t));
1493 eq2 = composite_for_idx(tbl, index_of(e));
1494
1495 assert(eq1->arity == 2 && eq2->arity == 2);
1496
1497 x = eq1->arg[0];
1498 if (x == eq2->arg[0]) return mk_bveq_ite(manager, c, x, eq1->arg[1], eq2->arg[1]);
1499 if (x == eq2->arg[1]) return mk_bveq_ite(manager, c, x, eq1->arg[1], eq2->arg[0]);
1500
1501 x = eq1->arg[1];
1502 if (x == eq2->arg[0]) return mk_bveq_ite(manager, c, x, eq1->arg[0], eq2->arg[1]);
1503 if (x == eq2->arg[1]) return mk_bveq_ite(manager, c, x, eq1->arg[0], eq2->arg[0]);
1504
1505 return ite_term(tbl, bool_type(tbl->types), c, t, e);
1506 }
1507
1508
1509 /*
1510 * Simplifications:
1511 * ite c x x --> x
1512 * ite true x y --> x
1513 * ite false x y --> y
1514 *
1515 * ite c x (not x) --> (c == x)
1516 *
1517 * ite c c y --> c or y
1518 * ite c x c --> c and x
1519 * ite c (not c) y --> (not c) and y
1520 * ite c x (not c) --> (not c) or x
1521 *
1522 * ite c true y --> c or y
1523 * ite c x false --> c and x
1524 * ite c false y --> (not c) and y
1525 * ite c x true --> (not c) or x
1526 *
1527 * Otherwise:
1528 * ite (not c) x y --> ite c y x
1529 */
mk_bool_ite(term_manager_t * manager,term_t c,term_t x,term_t y)1530 term_t mk_bool_ite(term_manager_t *manager, term_t c, term_t x, term_t y) {
1531 term_t aux;
1532
1533 if (x == y) return x;
1534 if (c == true_term) return x;
1535 if (c == false_term) return y;
1536
1537 if (opposite_bool_terms(x, y)) return mk_iff(manager, c, x);
1538
1539 if (c == x) return mk_binary_or(manager, c, y);
1540 if (c == y) return mk_binary_and(manager, c, x);
1541 if (opposite_bool_terms(c, x)) return mk_binary_and(manager, x, y);
1542 if (opposite_bool_terms(c, y)) return mk_binary_or(manager, x, y);
1543
1544 if (x == true_term) return mk_binary_or(manager, c, y);
1545 if (y == false_term) return mk_binary_and(manager, c, x);
1546 if (x == false_term) return mk_binary_and(manager, opposite_term(c), y);
1547 if (y == true_term) return mk_binary_or(manager, opposite_term(c), x);
1548
1549
1550 if (is_neg_term(c)) {
1551 c = opposite_term(c);
1552 aux = x; x = y; y = aux;
1553 }
1554
1555 if (is_pos_term(x) && is_pos_term(y) &&
1556 term_kind(manager->terms, x) == BV_EQ_ATOM &&
1557 term_kind(manager->terms, y) == BV_EQ_ATOM) {
1558 return mk_lifted_ite_bveq(manager, c, x, y);
1559 }
1560
1561 return ite_term(manager->terms, bool_type(manager->types), c, x, y);
1562 }
1563
1564
1565
1566
1567 /*
1568 * ARITHMETIC IF-THEN-ELSE
1569 */
1570
1571 /*
1572 * PUSH IF INSIDE INTEGER LINEAR POLYNOMIALS
1573 *
1574 * If t and e are polynomials with integer variables, we try to
1575 * rewrite (ite c t e) to r + a * (ite c t' e') where:
1576 * r = common part of t and e (cf. polynomials.h)
1577 * a = gcd of coefficients of (t - r) and (e - r).
1578 * t' = (t - r)/a
1579 * e' = (e - r)/a
1580 *
1581 * The code assumes that t and e are linear polynomials (i.e.,
1582 * the monomials are sorted in increasing variable order).
1583 */
1584
1585 /*
1586 * Remove every monomial of p whose variable is in a then divide the
1587 * result by c
1588 * - a = array of terms sorted in increasing order
1589 * a is terminatated by max_idx
1590 * - every element of a must be a variable of p
1591 * - c must be non-zero
1592 * - return the term (p - r)/c
1593 */
remove_monomials(term_manager_t * manager,polynomial_t * p,term_t * a,rational_t * c)1594 static term_t remove_monomials(term_manager_t *manager, polynomial_t *p, term_t *a, rational_t *c) {
1595 rba_buffer_t *b;
1596 monomial_t *mono;
1597 uint32_t i;
1598 term_t x;
1599
1600 assert(q_is_nonzero(c));
1601
1602 b = term_manager_get_arith_buffer(manager);
1603 reset_rba_buffer(b);
1604
1605 i = 0;
1606 mono = p->mono;
1607 x = mono->var;
1608
1609 // deal with the constant if any
1610 if (x == const_idx) {
1611 if (x == a[i]) {
1612 i ++;
1613 } else {
1614 assert(x < a[i]);
1615 rba_buffer_add_const(b, &mono->coeff);
1616 }
1617 mono ++;
1618 x = mono->var;
1619 }
1620
1621 // non constant monomials
1622 while (x < max_idx) {
1623 if (x == a[i]) {
1624 // skip t
1625 i ++;
1626 } else {
1627 assert(x < a[i]);
1628 rba_buffer_add_mono(b, &mono->coeff, pprod_for_term(manager->terms, x));
1629 }
1630 mono ++;
1631 x = mono->var;
1632 }
1633
1634 // divide by c
1635 if (! q_is_one(c)) {
1636 rba_buffer_div_const(b, c);
1637 }
1638
1639 // build the term from b
1640 return arith_buffer_to_term(manager->terms, b);
1641 }
1642
1643
1644 /*
1645 * Remove every monomial of p whose variable is not in a
1646 * then add c * t to the result.
1647 * - a must be an array of terms sorted in increasing order and terminated by max_idx
1648 * - all elements of a must be variables of p
1649 */
add_mono_to_common_part(term_manager_t * manager,polynomial_t * p,term_t * a,rational_t * c,term_t t)1650 static term_t add_mono_to_common_part(term_manager_t *manager, polynomial_t *p, term_t *a, rational_t *c, term_t t) {
1651 term_table_t *tbl;
1652 rba_buffer_t *b;
1653 monomial_t *mono;
1654 uint32_t i;
1655 term_t x;
1656
1657 tbl = manager->terms;
1658 b = term_manager_get_arith_buffer(manager);
1659 reset_rba_buffer(b);
1660
1661 i = 0;
1662 mono = p->mono;
1663 x = mono->var;
1664
1665 // constant monomial
1666 if (x == const_idx) {
1667 assert(x <= a[i]);
1668 if (x == a[i]) {
1669 rba_buffer_add_const(b, &mono->coeff);
1670 i ++;
1671 }
1672 mono ++;
1673 x = mono->var;
1674 }
1675
1676 // non constant monomials
1677 while (x < max_idx) {
1678 assert(x <= a[i]);
1679 if (x == a[i]) {
1680 rba_buffer_add_mono(b, &mono->coeff, pprod_for_term(tbl, x));
1681 i ++;
1682 }
1683 mono ++;
1684 x = mono->var;
1685 }
1686
1687 // add c * t
1688 rba_buffer_add_mono(b, c, pprod_for_term(tbl, t));
1689
1690 return arith_buffer_to_term(tbl, b);
1691 }
1692
1693
1694
1695 /*
1696 * Build t := p/c where c is a non-zero rational
1697 */
polynomial_div_const(term_manager_t * manager,polynomial_t * p,rational_t * c)1698 static term_t polynomial_div_const(term_manager_t *manager, polynomial_t *p, rational_t *c) {
1699 term_table_t *tbl;
1700 rba_buffer_t *b;
1701
1702 tbl = manager->terms;
1703 b = term_manager_get_arith_buffer(manager);
1704 reset_rba_buffer(b);
1705
1706 rba_buffer_add_monarray(b, p->mono, pprods_for_poly(tbl, p));
1707 term_table_reset_pbuffer(tbl);
1708 rba_buffer_div_const(b, c);
1709
1710 return arith_buffer_to_term(tbl, b);
1711 }
1712
1713
1714 /*
1715 * Build t := u * c
1716 */
mk_mul_term_const(term_manager_t * manager,term_t t,rational_t * c)1717 static term_t mk_mul_term_const(term_manager_t *manager, term_t t, rational_t *c) {
1718 term_table_t *tbl;
1719 rba_buffer_t *b;
1720
1721 tbl = manager->terms;
1722 b = term_manager_get_arith_buffer(manager);
1723 reset_rba_buffer(b);
1724 rba_buffer_add_mono(b, c, pprod_for_term(tbl, t));
1725
1726 return arith_buffer_to_term(tbl, b);
1727 }
1728
1729
1730 /*
1731 * Attempt to rewrite (ite c t e) to (r + a * (ite c t' e'))
1732 * - t and e must be distinct integer linear polynomials
1733 * - if r is null and a is one, it builds (ite c t e)
1734 * - if r is null and a is more than one, it builds a * (ite t' e')
1735 */
mk_integer_polynomial_ite(term_manager_t * manager,term_t c,term_t t,term_t e)1736 static term_t mk_integer_polynomial_ite(term_manager_t *manager, term_t c, term_t t, term_t e) {
1737 term_table_t *tbl;
1738 polynomial_t *p, *q;
1739 ivector_t *v;
1740 rational_t *r0;
1741 term_t ite;
1742
1743 tbl = manager->terms;
1744
1745 assert(is_integer_term(tbl, t) && is_integer_term(tbl, e));
1746 assert(is_linear_poly(tbl, t) && is_linear_poly(tbl, e));
1747
1748 p = poly_term_desc(tbl, t); // then part
1749 q = poly_term_desc(tbl, e); // else part
1750 assert(! equal_polynomials(p, q));
1751
1752 /*
1753 * Collect the common part of p and q into v
1754 * + the common factor into r0
1755 */
1756 v = &manager->vector0;
1757 ivector_reset(v);
1758 monarray_pair_common_part(p->mono, q->mono, v);
1759 ivector_push(v, max_idx); // end marker
1760
1761 r0 = &manager->r0;
1762 monarray_pair_non_common_gcd(p->mono, q->mono, r0);
1763 assert(q_is_pos(r0) && q_is_integer(r0));
1764
1765 if (v->size > 0) {
1766 // the common part is non-null
1767 t = remove_monomials(manager, p, v->data, r0); // t is (p - common)/r0
1768 e = remove_monomials(manager, q, v->data, r0); // e is (q - common)/r0
1769 } else if (! q_is_one(r0)) {
1770 // no common part, common factor > 1
1771 t = polynomial_div_const(manager, p, r0); // t is p/r0
1772 e = polynomial_div_const(manager, q, r0); // e is q/r0
1773 }
1774
1775 // build (ite c t e): type int
1776 ite = ite_term(tbl, int_type(tbl->types), c, t, e);
1777
1778 if (v->size > 0) {
1779 // build common + r0 * ite
1780 ite = add_mono_to_common_part(manager, p, v->data, r0, ite);
1781 } else if (! q_is_one(r0)) {
1782 // common factor > 1: build r0 * ite
1783 ite = mk_mul_term_const(manager, ite, r0);
1784 }
1785
1786 // cleanup
1787 ivector_reset(v);
1788
1789 return ite;
1790 }
1791
1792
1793 /*
1794 * OFFSET ITE
1795 */
1796
1797 /*
1798 * Auxiliary function: builds t + (ite c k1 k2)
1799 * - if is_int is true then both k1 and k2 are assumed to be integer
1800 * so (ite c k1 k2) has type int
1801 * - otherwise (ite c k1 k2) has type real
1802 */
mk_offset_ite(term_manager_t * manager,term_t t,type_t c,term_t k1,term_t k2,bool is_int)1803 static term_t mk_offset_ite(term_manager_t *manager, term_t t, type_t c, term_t k1, term_t k2, bool is_int) {
1804 term_table_t *tbl;
1805 rba_buffer_t *b;
1806 type_t tau;
1807 term_t ite;
1808
1809 tbl = manager->terms;
1810 b = term_manager_get_arith_buffer(manager);
1811
1812 tau = is_int ? int_type(tbl->types) : real_type(tbl->types);
1813 ite = ite_term(tbl, tau, c, k1, k2); // (ite c k1 k2)
1814 reset_rba_buffer(b);
1815 rba_buffer_add_term(b, tbl, t);
1816 rba_buffer_add_term(b, tbl, ite); // t + (ite c k1 k2)
1817 return arith_buffer_to_term(tbl, b);
1818 }
1819
1820
1821 /*
1822 * Attempt to apply the offset rule to (ite c t e):
1823 * 1) If t is of the form (k + e), builds e + (ite c k 0)
1824 * 2) If e is of the form (k + t), builds t + (ite c 0 k)
1825 * 3) Otherwise returns NULL_TERM
1826 */
try_offset_ite(term_manager_t * manager,term_t c,term_t t,term_t e)1827 static term_t try_offset_ite(term_manager_t *manager, term_t c, term_t t, term_t e) {
1828 term_table_t *tbl;
1829 polynomial_t *p;
1830 rational_t *k;
1831 term_t offset;
1832 bool is_int;
1833
1834 tbl = manager->terms;
1835 k = &manager->r0;
1836
1837 if (term_kind(tbl, t) == ARITH_POLY) {
1838 p = poly_term_desc(tbl, t);
1839 if (polynomial_is_const_plus_var(p, e)) {
1840 // t is e + k for some non-zero constant k
1841 // (ite c t e) --> e + (ite c k 0)
1842 monarray_constant(p->mono, k);
1843 is_int = q_is_integer(k);
1844 offset = arith_constant(tbl, k);
1845 return mk_offset_ite(manager, e, c, offset, zero_term, is_int);
1846 }
1847 }
1848
1849 if (term_kind(tbl, e) == ARITH_POLY) {
1850 p = poly_term_desc(tbl, e);
1851 if (polynomial_is_const_plus_var(p, t)) {
1852 // e is t + k for some non-zero constant k
1853 // (ite c t e) --> t + (ite c 0 k)
1854 monarray_constant(p->mono, k);
1855 is_int = q_is_integer(k);
1856 offset = arith_constant(tbl, k);
1857 return mk_offset_ite(manager, t, c, zero_term, offset, is_int);
1858 }
1859 }
1860
1861 return NULL_TERM;
1862 }
1863
1864
1865
1866
1867 /*
1868 * PUSH IF INSIDE ARRAY/FUNCTION UPDATES
1869 *
1870 * Rewrite rules:
1871 * (ite c (update A (i1 ... ik) v) A) --> (update A (i1 ... ik) (ite c v (A i1 ... ik)))
1872 * (ite c A (update A (i1 ... ik) v)) --> (update A (i1 ... ik) (ite c (A i1 ... ik) v))
1873 * (ite c (update A (i1 ... ik) v) (update A (i1 ... ik) w)) -->
1874 * (update A (i1 ... ik) (ite c v w))
1875 */
1876
1877
1878 /*
1879 * Auxiliary function: check whether terms a[0...n-1] and b[0 .. n-1] are equal
1880 */
equal_term_arrays(uint32_t n,const term_t * a,const term_t * b)1881 static bool equal_term_arrays(uint32_t n, const term_t *a, const term_t *b) {
1882 uint32_t i;
1883
1884 for (i=0; i<n; i++) {
1885 if (a[i] != b[i]) return false;
1886 }
1887 return true;
1888 }
1889
1890
1891 /*
1892 * Check whether one of the rewrite rules above is applicable to (ite c t e tau)
1893 * - t and e have a function type
1894 * - it it is apply it and return the result
1895 * - otherwise, return NULL_TERM
1896 */
simplify_ite_update(term_manager_t * manager,term_t c,term_t t,term_t e,type_t tau)1897 static term_t simplify_ite_update(term_manager_t *manager, term_t c, term_t t, term_t e, type_t tau) {
1898 term_table_t *terms;
1899 composite_term_t *update1, *update2;
1900 bool t_is_update, e_is_update;
1901 uint32_t n;
1902 term_t aux;
1903 type_t sigma;
1904
1905 terms = manager->terms;
1906
1907 assert(is_function_term(terms, t) && is_function_term(terms, e));
1908
1909 t_is_update = (term_kind(terms, t) == UPDATE_TERM);
1910 e_is_update = (term_kind(terms, e) == UPDATE_TERM);
1911 sigma = function_type_range(manager->types, tau);
1912
1913 if (t_is_update && e_is_update) {
1914 update1 = update_term_desc(terms, t);
1915 update2 = update_term_desc(terms, e);
1916
1917 n = update1->arity;
1918 assert(n >= 3 && n == update2->arity);
1919
1920 if (equal_term_arrays(n-1, update1->arg, update2->arg)) {
1921 // t is (update f a[1] ... a[n-2] v)
1922 // e is (update f a[1] ... a[n-2] w)
1923 aux = mk_ite(manager, c, update1->arg[n-1], update2->arg[n-1], sigma); // (ite c v w)
1924 return mk_update(manager, update1->arg[0], n-2, update1->arg + 1, aux);
1925 }
1926
1927 } else if (t_is_update) {
1928 update1 = update_term_desc(terms, t);
1929 if (update1->arg[0] == e) {
1930 // t is (update e a[1] ... a[n-2] v)
1931 // (ite c t e) --> (update e a[1] ... a[n-2] (ite c v (e a[1] ... a[n-2])))
1932 n = update1->arity;
1933 assert(n >= 3);
1934
1935 aux = mk_application(manager, e, n-2, update1->arg + 1); // (e a[1] ... a[n-2])
1936 aux = mk_ite(manager, c, update1->arg[n-1], aux, sigma); // (ite c v (e a[1] ... a[n-2]))
1937 return mk_update(manager, e, n-2, update1->arg + 1, aux);
1938 }
1939
1940 } else if (e_is_update) {
1941 update2 = update_term_desc(terms, e);
1942 if (update2->arg[0] == t) {
1943 // e is (update t a[1] ... a[n-2] w)
1944 // (ite c t e) --> (update t a[1] ... a[n-2] (ite c (t (a[1] ... a[n-2]) w)))
1945 n = update2->arity;
1946 assert(n >= 3);
1947
1948 aux = mk_application(manager, t, n-2, update2->arg + 1); // (t a[1] ... a[n-2])
1949 aux = mk_ite(manager, c, aux, update2->arg[n-1], sigma); // (ite c (t a[1] ... a[n-2]) w)
1950 return mk_update(manager, t, n-2, update2->arg + 1, aux);
1951 }
1952 }
1953
1954 return NULL_TERM;
1955 }
1956
1957
1958
1959
1960 /*
1961 * GENERIC IF-THEN-ELSE
1962 */
1963
1964 /*
1965 * Simplify t assuming c holds
1966 * - c must be a boolean term.
1967 *
1968 * Rules:
1969 * (ite c x y) --> x
1970 * (ite ~c x y) --> y
1971 */
simplify_in_context(term_table_t * tbl,term_t c,term_t t)1972 static term_t simplify_in_context(term_table_t *tbl, term_t c, term_t t) {
1973 composite_term_t *d;
1974
1975 assert(is_boolean_term(tbl, c) && good_term(tbl, t));
1976
1977 while (is_ite_term(tbl, t)) {
1978 d = ite_term_desc(tbl, t);
1979 if (d->arg[0] == c) {
1980 t = d->arg[1];
1981 } else if (opposite_bool_terms(c, d->arg[0])) {
1982 t = d->arg[2];
1983 } else {
1984 break;
1985 }
1986 }
1987
1988 return t;
1989 }
1990
1991
1992 /*
1993 * If-then-else: (if c then t else e)
1994 * - c must be Boolean
1995 * - t and e must have compatible types tau1 and tau2
1996 * - tau must be the least common supertype of tau1 and tau2
1997 *
1998 * Simplifications
1999 * ite c (ite c x y) z --> ite c x z
2000 * ite c (ite ~c x y) z --> ite c y z
2001 * ite c x (ite c y z) --> ite c x z
2002 * ite c x (ite ~c y z) --> ite c x y
2003 *
2004 * ite true x y --> x
2005 * ite false x y --> y
2006 * ite c x x --> x
2007 *
2008 * Otherwise:
2009 * ite (not c) x y --> ite c y x
2010 *
2011 * Plus special trick for integer polynomials:
2012 * ite c (d * p1) (d * p2) --> d * (ite c p1 p2)
2013 *
2014 */
mk_ite(term_manager_t * manager,term_t c,term_t t,term_t e,type_t tau)2015 term_t mk_ite(term_manager_t *manager, term_t c, term_t t, term_t e, type_t tau) {
2016 term_t aux;
2017
2018 // boolean ite
2019 if (is_boolean_type(tau)) {
2020 assert(is_boolean_term(manager->terms, t) &&
2021 is_boolean_term(manager->terms, e));
2022 return mk_bool_ite(manager, c, t, e);
2023 }
2024
2025 // bit-vector ite
2026 if (is_bv_type(manager->types, tau)) {
2027 assert(is_bitvector_term(manager->terms, t) &&
2028 is_bitvector_term(manager->terms, e));
2029 return mk_bv_ite(manager, c, t, e);
2030 }
2031
2032 // general case
2033 if (c == true_term) return t;
2034 if (c == false_term) return e;
2035
2036 t = simplify_in_context(manager->terms, c, t);
2037 e = simplify_in_context(manager->terms, opposite_term(c), e);
2038 if (t == e) return t;
2039
2040 if (is_neg_term(c)) {
2041 // ite (not c) x y --> ite c y x
2042 c = opposite_term(c);
2043 aux = t; t = e; e = aux;
2044 }
2045
2046 // rewriting of arithmetic if-then-elses
2047 if (manager->simplify_ite && is_arithmetic_type(tau)) {
2048 if (is_integer_type(tau) &&
2049 is_linear_poly(manager->terms, t) &&
2050 is_linear_poly(manager->terms, e)) {
2051 return mk_integer_polynomial_ite(manager, c, t, e);
2052 }
2053
2054 aux = try_offset_ite(manager, c, t, e);
2055 if (aux != NULL_TERM) return aux;
2056 }
2057
2058 // check for array updates
2059 if (is_function_type(manager->types, tau)) {
2060 aux = simplify_ite_update(manager, c, t, e, tau);
2061 if (aux != NULL_TERM) return aux;
2062 }
2063
2064 return ite_term(manager->terms, tau, c, t, e);
2065 }
2066
2067
2068
2069
2070
2071 /**********************
2072 * ARITHMETIC ATOMS *
2073 *********************/
2074
2075 /*
2076 * Auxiliary function: try to simplify (t1 == t2)
2077 * using the following rules:
2078 * (ite c x y) == x --> c provided x != y holds
2079 * (ite c x y) == y --> ~c provided x != y holds
2080 *
2081 * - return the result if one of these rules apply
2082 * - return NULL_TERM otherwise.
2083 */
check_aritheq_simplifies(term_table_t * tbl,term_t t1,term_t t2)2084 static term_t check_aritheq_simplifies(term_table_t *tbl, term_t t1, term_t t2) {
2085 composite_term_t *d;
2086 term_t x, y;
2087
2088 assert(is_arithmetic_term(tbl, t1) && is_arithmetic_term(tbl, t2));
2089
2090 if (is_ite_term(tbl, t1)) {
2091 // (ite c x y) == t2
2092 d = ite_term_desc(tbl, t1);
2093 x = d->arg[1];
2094 y = d->arg[2];
2095 if (x == t2 && disequal_arith_terms(tbl, y, t2, true)) {
2096 return d->arg[0];
2097 }
2098 if (y == t2 && disequal_arith_terms(tbl, x, t2, true)) {
2099 return opposite_term(d->arg[0]);
2100 }
2101 }
2102
2103 if (is_ite_term(tbl, t2)) {
2104 // t1 == (ite c x y)
2105 d = ite_term_desc(tbl, t2);
2106 x = d->arg[1];
2107 y = d->arg[2];
2108 if (x == t1 && disequal_arith_terms(tbl, y, t1, true)) {
2109 return d->arg[0];
2110 }
2111 if (y == t1 && disequal_arith_terms(tbl, x, t1, true)) {
2112 return opposite_term(d->arg[0]);
2113 }
2114 }
2115
2116 return NULL_TERM;
2117 }
2118
2119
2120 /*
2121 * Auxiliary function: try to simplify (t == 0)
2122 * Rules:
2123 * (ite c 0 y) == 0 --> c provided y != 0
2124 * (ite c x 0) == 0 --> ~c provided x != 0
2125 */
check_arith_eq0_simplifies(term_table_t * tbl,term_t t,bool check_ite)2126 static term_t check_arith_eq0_simplifies(term_table_t *tbl, term_t t, bool check_ite) {
2127 composite_term_t *d;
2128 term_t x, y;
2129
2130 assert(is_arithmetic_term(tbl, t));
2131
2132 if (is_ite_term(tbl, t)) {
2133 // (ite c x y) == 0
2134 d = ite_term_desc(tbl, t);
2135 x = d->arg[1];
2136 y = d->arg[2];
2137 if (x == zero_term && arith_term_is_nonzero(tbl, y, check_ite)) {
2138 return d->arg[0];
2139 }
2140 if (y == zero_term && arith_term_is_nonzero(tbl, x, check_ite)) {
2141 return opposite_term(d->arg[0]);
2142 }
2143 }
2144
2145 return NULL_TERM;
2146 }
2147
2148 /*
2149 * Auxiliary function: build binary equality (t1 == t2)
2150 * for two arithmetic terms t1 and t2.
2151 * - try simplification and normalize first
2152 */
mk_arith_bineq_atom(term_table_t * tbl,term_t t1,term_t t2,bool simplify_ite)2153 static term_t mk_arith_bineq_atom(term_table_t *tbl, term_t t1, term_t t2, bool simplify_ite) {
2154 term_t aux;
2155
2156 assert(is_arithmetic_term(tbl, t1) && is_arithmetic_term(tbl, t2));
2157
2158 if (disequal_arith_terms(tbl, t1, t2, simplify_ite)) {
2159 return false_term;
2160 }
2161
2162 if (simplify_ite) {
2163 aux = check_aritheq_simplifies(tbl, t1, t2);
2164 if (aux != NULL_TERM) {
2165 return aux;
2166 }
2167 }
2168
2169 // normalize: put the smallest term on the left
2170 if (t1 > t2) {
2171 aux = t1; t1 = t2; t2 = aux;
2172 }
2173
2174 return arith_bineq_atom(tbl, t1, t2);
2175 }
2176
2177
2178 /*
2179 * Auxiliary function: builds equality (t == 0)
2180 * - try to simplify and normalize then build (arith-eq0 t)
2181 */
mk_arith_eq0_atom(term_table_t * tbl,term_t t,bool simplify_ite)2182 static term_t mk_arith_eq0_atom(term_table_t *tbl, term_t t, bool simplify_ite) {
2183 term_t aux;
2184
2185 assert(is_arithmetic_term(tbl, t));
2186
2187 if (arith_term_is_nonzero(tbl, t, simplify_ite)) {
2188 return false_term;
2189 }
2190
2191 if (simplify_ite) {
2192 aux = check_arith_eq0_simplifies(tbl, t, simplify_ite);
2193 if (aux != NULL_TERM) {
2194 return aux;
2195 }
2196 }
2197
2198 return arith_eq_atom(tbl, t); // (t == 0)
2199 }
2200
2201
2202 /*
2203 * Construct the atom (b == 0) then reset b.
2204 *
2205 * Normalize b first.
2206 * - simplify to true if b is the zero polynomial
2207 * - simplify to false if b is constant and non-zero
2208 * - rewrite to (t1 == t2) if that's possible.
2209 * - otherwise, create a polynomial term t from b
2210 * and return the atom (t == 0).
2211 */
mk_arith_eq0(term_manager_t * manager,rba_buffer_t * b)2212 term_t mk_arith_eq0(term_manager_t *manager, rba_buffer_t *b) {
2213 return mk_direct_arith_eq0(manager->terms, b, manager->simplify_ite);
2214 }
2215
2216
2217
2218
2219 /*
2220 * Auxiliary function: try to simplify (t >= 0)
2221 * using the following rules:
2222 * (ite c x y) >= 0 --> c if x >= 0 and y < 0
2223 * (ite c x y) >= 0 --> ~c if x < 0 and y >= 0
2224 *
2225 * return NULL_TERM if these simplifications don't work.
2226 * return the result otherwise
2227 */
check_arithge_simplifies(term_table_t * tbl,term_t t,bool check_ite)2228 static term_t check_arithge_simplifies(term_table_t *tbl, term_t t, bool check_ite) {
2229 composite_term_t *d;
2230 term_t x, y;
2231
2232 assert(is_arithmetic_term(tbl, t));
2233
2234 if (is_ite_term(tbl, t)) {
2235 d = ite_term_desc(tbl, t);
2236 x = d->arg[1];
2237 y = d->arg[2];
2238
2239 if (arith_term_is_nonneg(tbl, x, true) &&
2240 arith_term_is_negative(tbl, y, check_ite)) {
2241 return d->arg[0];
2242 }
2243
2244 if (arith_term_is_negative(tbl, x, check_ite) &&
2245 arith_term_is_nonneg(tbl, y, true)) {
2246 return opposite_term(d->arg[0]);
2247 }
2248 }
2249
2250 return NULL_TERM;
2251 }
2252
2253
2254 /*
2255 * Build the atom (t >= 0)
2256 * - try simplifications first
2257 */
mk_arith_geq_atom(term_table_t * tbl,term_t t,bool simplify_ite)2258 static term_t mk_arith_geq_atom(term_table_t *tbl, term_t t, bool simplify_ite) {
2259 term_t aux;
2260
2261 assert(is_arithmetic_term(tbl, t));
2262
2263 if (arith_term_is_nonneg(tbl, t, simplify_ite)) {
2264 return true_term;
2265 }
2266
2267 if (simplify_ite) {
2268 aux = check_arithge_simplifies(tbl, t, simplify_ite);
2269 if (aux != NULL_TERM) {
2270 return aux;
2271 }
2272 }
2273
2274 return arith_geq_atom(tbl, t);
2275 }
2276
2277
2278 /*
2279 * Construct the atom (b == 0) then reset b.
2280 *
2281 * Normalize b first.
2282 * - simplify to true if b is the zero polynomial
2283 * - simplify to false if b is constant and non-zero
2284 * - rewrite to (t1 == t2) if that's possible.
2285 * - otherwise, create a polynomial term t from b
2286 * and return the atom (t == 0).
2287 */
mk_direct_arith_eq0(term_table_t * tbl,rba_buffer_t * b,bool simplify_ite)2288 term_t mk_direct_arith_eq0(term_table_t *tbl, rba_buffer_t *b, bool simplify_ite) {
2289 mono_t *m[2], *m1, *m2;
2290 pprod_t *r1, *r2;
2291 rational_t r0;
2292 term_t t1, t2, t;
2293 uint32_t n;
2294
2295 assert(b->ptbl == tbl->pprods);
2296
2297 n = b->nterms;
2298 if (n == 0) {
2299 // b is zero
2300 t = true_term;
2301
2302 } else if (n == 1) {
2303 /*
2304 * b is a1 * r1 with a_1 != 0
2305 * (a1 * r1 == 0) is false if r1 is the empty product
2306 * (a1 * r1 == 0) simplifies to (r1 == 0) otherwise
2307 */
2308 m1 = rba_buffer_root_mono(b);
2309 r1 = m1->prod;
2310 assert(q_is_nonzero(&m1->coeff));
2311 if (r1 == empty_pp) {
2312 t = false_term;
2313 } else {
2314 t1 = pp_is_var(r1) ? var_of_pp(r1) : pprod_term(tbl, r1);
2315 t = mk_arith_eq0_atom(tbl, t1, simplify_ite); // atom r1 = 0
2316 }
2317
2318 } else if (n == 2) {
2319 /*
2320 * b is a1 * r1 + a2 * r2
2321 * Simplifications:
2322 * - rewrite (b == 0) to (r2 == -a1/a2) if r1 is the empty product
2323 * - rewrite (b == 0) to (r1 == r2) is a1 + a2 = 0
2324 */
2325 rba_buffer_monomial_pair(b, m);
2326 m1 = m[0];
2327 m2 = m[1];
2328 r1 = m1->prod;
2329 r2 = m2->prod;
2330 assert(q_is_nonzero(&m1->coeff) && q_is_nonzero(&m2->coeff));
2331
2332 q_init(&r0);
2333
2334 if (r1 == empty_pp) {
2335 q_set_neg(&r0, &m1->coeff);
2336 q_div(&r0, &m2->coeff); // r0 is -a1/a2
2337 t1 = arith_constant(tbl, &r0);
2338 t2 = pp_is_var(r2) ? var_of_pp(r2) : pprod_term(tbl, r2);
2339 t = mk_arith_bineq_atom(tbl, t1, t2, simplify_ite);
2340
2341 } else {
2342 q_set(&r0, &m1->coeff);
2343 q_add(&r0, &m2->coeff);
2344 if (q_is_zero(&r0)) {
2345 t1 = pp_is_var(r1) ? var_of_pp(r1) : pprod_term(tbl, r1);
2346 t2 = pp_is_var(r2) ? var_of_pp(r2) : pprod_term(tbl, r2);
2347 t = mk_arith_bineq_atom(tbl, t1, t2, simplify_ite);
2348
2349 } else {
2350 // no simplification
2351 t = arith_poly(tbl, b);
2352 t = arith_eq_atom(tbl, t);
2353 }
2354 }
2355
2356 q_clear(&r0);
2357
2358 } else {
2359 /*
2360 * more than 2 monomials: don't simplify
2361 */
2362 t = arith_poly(tbl, b);
2363 t = arith_eq_atom(tbl, t);
2364 }
2365
2366
2367 reset_rba_buffer(b);
2368 assert(good_term(tbl, t) && is_boolean_term(tbl, t));
2369
2370 return t;
2371 }
2372
2373
2374 /*
2375 * Construct the atom (b >= 0) then reset b.
2376 *
2377 * Normalize b first then check for simplifications.
2378 * - simplify to true or false if b is a constant
2379 * - otherwise build a term t from b and return the atom (t >= 0)
2380 */
mk_direct_arith_geq0(term_table_t * tbl,rba_buffer_t * b,bool simplify_ite)2381 term_t mk_direct_arith_geq0(term_table_t *tbl, rba_buffer_t *b, bool simplify_ite) {
2382 mono_t *m;
2383 pprod_t *r;
2384 term_t t;
2385 uint32_t n;
2386
2387 assert(b->ptbl == tbl->pprods);
2388
2389 n = b->nterms;
2390 if (n == 0) {
2391 // b is zero
2392 t = true_term;
2393 } else if (n == 1) {
2394 /*
2395 * b is a * r with a != 0
2396 * if r is the empty product, (b >= 0) simplifies to true or false
2397 * otherwise, (b >= 0) simplifies either to r >= 0 or -r >= 0
2398 */
2399 m = rba_buffer_root_mono(b); // unique monomial of b
2400 r = m->prod;
2401 if (q_is_pos(&m->coeff)) {
2402 // a > 0
2403 if (r == empty_pp) {
2404 t = true_term;
2405 } else {
2406 t = pp_is_var(r) ? var_of_pp(r) : pprod_term(tbl, r);
2407 t = mk_arith_geq_atom(tbl, t, simplify_ite); // r >= 0
2408 }
2409 } else {
2410 // a < 0
2411 if (r == empty_pp) {
2412 t = false_term;
2413 } else {
2414 q_set_minus_one(&m->coeff); // force a := -1
2415 t = arith_poly(tbl, b);
2416 t = mk_arith_geq_atom(tbl, t, simplify_ite);
2417 }
2418 }
2419
2420 } else {
2421 // no simplification (for now).
2422 // could try to reduce the coefficients?
2423 t = arith_poly(tbl, b);
2424 t = mk_arith_geq_atom(tbl, t, simplify_ite);
2425 }
2426
2427 reset_rba_buffer(b);
2428 assert(good_term(tbl, t) && is_boolean_term(tbl, t));
2429
2430 return t;
2431 }
2432
2433
2434 /*
2435 * Same thing: using a manager
2436 */
mk_arith_geq0(term_manager_t * manager,rba_buffer_t * b)2437 term_t mk_arith_geq0(term_manager_t *manager, rba_buffer_t *b) {
2438 return mk_direct_arith_geq0(manager->terms, b, manager->simplify_ite);
2439 }
2440
2441
2442 /*
2443 * Cheap lift-if decomposition:
2444 * - decompose (ite c x y) (ite c z u) ---> [c, x, z, y, u]
2445 * - decompose (ite c x y) z ---> [c, x, z, y, z]
2446 * - decompose x (ite c y z) ---> [c, x, y, x, z]
2447 *
2448 * The result is stored into the lift_result_t object:
2449 * - for example: [c, x, z, y, u] is stored as
2450 * cond = c, left1 = x, left2 = z, right1 = y, right2 = u
2451 * - the function return true if the decomposition succeeds, false otherwise
2452 *
2453 * NOTE: we don't want to apply these lift-if rules if one or both terms
2454 * are special if-then-elses.
2455 */
2456 typedef struct lift_result_s {
2457 term_t cond;
2458 term_t left1, left2;
2459 term_t right1, right2;
2460 } lift_result_t;
2461
2462
check_for_lift_if(term_table_t * tbl,term_t t1,term_t t2,lift_result_t * d)2463 static bool check_for_lift_if(term_table_t *tbl, term_t t1, term_t t2, lift_result_t *d) {
2464 composite_term_t *ite1, *ite2;
2465 term_t cond;
2466
2467 assert(is_pos_term(t1) && is_pos_term(t2));
2468
2469 if (term_kind(tbl, t1) == ITE_TERM) {
2470 if (term_kind(tbl, t2) == ITE_TERM) {
2471 // both are (if-then-else ..)
2472 ite1 = ite_term_desc(tbl, t1);
2473 ite2 = ite_term_desc(tbl, t2);
2474
2475 cond = ite1->arg[0];
2476 if (cond == ite2->arg[0]) {
2477 d->cond = cond;
2478 d->left1 = ite1->arg[1];
2479 d->left2 = ite2->arg[1];
2480 d->right1 = ite1->arg[2];
2481 d->right2 = ite2->arg[2];
2482 return true;
2483 }
2484
2485 } else {
2486 // t1 is (if-then-else ..) t2 is not
2487 ite1 = ite_term_desc(tbl, t1);
2488 d->cond = ite1->arg[0];
2489 d->left1 = ite1->arg[1];
2490 d->left2 = t2;
2491 d->right1 = ite1->arg[2];
2492 d->right2 = t2;
2493 return true;
2494
2495 }
2496 } else if (term_kind(tbl, t2) == ITE_TERM) {
2497 // t2 is (if-then-else ..) t1 is not
2498
2499 ite2 = ite_term_desc(tbl, t2);
2500 d->cond = ite2->arg[0];
2501 d->left1 = t1;
2502 d->left2 = ite2->arg[1];
2503 d->right1 = t1;
2504 d->right2 = ite2->arg[2];
2505 return true;
2506 }
2507
2508 return false;
2509 }
2510
2511
2512
2513
2514
2515
2516 /*
2517 * Store t1 - t2 in buffer b
2518 */
mk_arith_diff(term_manager_t * manager,rba_buffer_t * b,term_t t1,term_t t2)2519 static void mk_arith_diff(term_manager_t *manager, rba_buffer_t *b, term_t t1, term_t t2) {
2520 reset_rba_buffer(b);
2521 rba_buffer_add_term(b, manager->terms, t1);
2522 rba_buffer_sub_term(b, manager->terms, t2);
2523 }
2524
2525
2526 /*
2527 * Build the term (ite c (aritheq t1 t2) (aritheq t3 t4))
2528 * - c is a boolean term
2529 * - t1, t2, t3, t4 are all arithmetic terms
2530 */
mk_lifted_aritheq(term_manager_t * manager,term_t c,term_t t1,term_t t2,term_t t3,term_t t4)2531 static term_t mk_lifted_aritheq(term_manager_t *manager, term_t c, term_t t1, term_t t2, term_t t3, term_t t4) {
2532 rba_buffer_t *b;
2533 term_t left, right;
2534
2535 b = term_manager_get_arith_buffer(manager);
2536
2537 mk_arith_diff(manager, b, t1, t2);
2538 left = mk_arith_eq0(manager, b);
2539 mk_arith_diff(manager, b, t3, t4);
2540 right = mk_arith_eq0(manager, b);
2541
2542 return mk_bool_ite(manager, c, left, right);
2543 }
2544
2545 // Variant: apply the cheap lift-if rules recursively
mk_lifted_aritheq_recur(term_manager_t * manager,term_t c,term_t t1,term_t t2,term_t t3,term_t t4)2546 static term_t mk_lifted_aritheq_recur(term_manager_t *manager, term_t c, term_t t1, term_t t2, term_t t3, term_t t4) {
2547 term_t left, right;
2548
2549 left = mk_arith_eq(manager, t1, t2);
2550 right = mk_arith_eq(manager, t3, t4);
2551 return mk_bool_ite(manager, c, left, right);
2552 }
2553
2554
2555 /*
2556 * Build the term (ite c (arithge t1 t2) (arithge t3 t4))
2557 * - c is a boolean term
2558 * - t1, t2, t3, t4 are all arithmetic terms
2559 */
mk_lifted_arithgeq(term_manager_t * manager,term_t c,term_t t1,term_t t2,term_t t3,term_t t4)2560 static term_t mk_lifted_arithgeq(term_manager_t *manager, term_t c, term_t t1, term_t t2, term_t t3, term_t t4) {
2561 rba_buffer_t *b;
2562 term_t left, right;
2563
2564 b = term_manager_get_arith_buffer(manager);
2565
2566 mk_arith_diff(manager, b, t1, t2);
2567 left = mk_arith_geq0(manager, b);
2568 mk_arith_diff(manager, b, t3, t4);
2569 right = mk_arith_geq0(manager, b);
2570
2571 return mk_bool_ite(manager, c, left, right);
2572 }
2573
2574 // Variant: apply the cheap lift-if rules recursively
mk_lifted_arithgeq_recur(term_manager_t * manager,term_t c,term_t t1,term_t t2,term_t t3,term_t t4)2575 static term_t mk_lifted_arithgeq_recur(term_manager_t *manager, term_t c, term_t t1, term_t t2, term_t t3, term_t t4) {
2576 term_t left, right;
2577
2578 left = mk_arith_geq(manager, t1, t2);
2579 right = mk_arith_geq(manager, t3, t4);
2580 return mk_bool_ite(manager, c, left, right);
2581 }
2582
2583
2584
2585 /*
2586 * BINARY ATOMS
2587 */
2588
2589 /*
2590 * Equality term (= t1 t2)
2591 *
2592 * Apply the cheap lift-if rules
2593 * (eq x (ite c y z)) ---> (ite c (eq x y) (eq x z)) provided x is not an if term
2594 * (eq (ite c x y) z)) ---> (ite c (eq x z) (eq y z)) provided z is not an if term
2595 * (eq (ite c x y) (ite c z u)) --> (ite c (eq x z) (eq y u))
2596 *
2597 */
mk_arith_eq(term_manager_t * manager,term_t t1,term_t t2)2598 term_t mk_arith_eq(term_manager_t *manager, term_t t1, term_t t2) {
2599 rba_buffer_t *b;
2600 lift_result_t tmp;
2601
2602 assert(is_arithmetic_term(manager->terms, t1) &&
2603 is_arithmetic_term(manager->terms, t2));
2604
2605 if (false && manager->simplify_ite && check_for_lift_if(manager->terms, t1, t2, &tmp)) {
2606 if (true) {
2607 return mk_lifted_aritheq(manager, tmp.cond, tmp.left1, tmp.left2, tmp.right1, tmp.right2);
2608 } else {
2609 return mk_lifted_aritheq_recur(manager, tmp.cond, tmp.left1, tmp.left2, tmp.right1, tmp.right2);
2610 }
2611 }
2612
2613 b = term_manager_get_arith_buffer(manager);
2614 mk_arith_diff(manager, b, t1, t2);
2615 return mk_arith_eq0(manager, b);
2616 }
2617
2618
2619 /*
2620 * Inequality: (>= t1 t2)
2621 *
2622 * Try the cheap lift-if rules.
2623 */
mk_arith_geq(term_manager_t * manager,term_t t1,term_t t2)2624 term_t mk_arith_geq(term_manager_t *manager, term_t t1, term_t t2) {
2625 rba_buffer_t *b;
2626 lift_result_t tmp;
2627
2628 assert(is_arithmetic_term(manager->terms, t1) &&
2629 is_arithmetic_term(manager->terms, t2));
2630
2631 if (false && check_for_lift_if(manager->terms, t1, t2, &tmp)) {
2632 if (true) {
2633 return mk_lifted_arithgeq(manager, tmp.cond, tmp.left1, tmp.left2, tmp.right1, tmp.right2);
2634 } else {
2635 return mk_lifted_arithgeq_recur(manager, tmp.cond, tmp.left1, tmp.left2, tmp.right1, tmp.right2);
2636 }
2637 }
2638
2639 b = term_manager_get_arith_buffer(manager);
2640 mk_arith_diff(manager, b, t1, t2);
2641 return mk_arith_geq0(manager, b);
2642 }
2643
2644
2645 /*
2646 * Derived atoms
2647 */
2648
2649 // t1 != t2 --> not (t1 == t2)
mk_arith_neq(term_manager_t * manager,term_t t1,term_t t2)2650 term_t mk_arith_neq(term_manager_t *manager, term_t t1, term_t t2) {
2651 return opposite_term(mk_arith_eq(manager, t1, t2));
2652 }
2653
2654 // t1 <= t2 --> t2 >= t1
mk_arith_leq(term_manager_t * manager,term_t t1,term_t t2)2655 term_t mk_arith_leq(term_manager_t *manager, term_t t1, term_t t2) {
2656 return mk_arith_geq(manager, t2, t1);
2657 }
2658
2659 // t1 > t2 --> not (t2 >= t1)
mk_arith_gt(term_manager_t * manager,term_t t1,term_t t2)2660 term_t mk_arith_gt(term_manager_t *manager, term_t t1, term_t t2) {
2661 return opposite_term(mk_arith_geq(manager, t2, t1));
2662 }
2663
2664 // t1 < t2 --> not (t1 >= t2)
mk_arith_lt(term_manager_t * manager,term_t t1,term_t t2)2665 term_t mk_arith_lt(term_manager_t *manager, term_t t1, term_t t2) {
2666 return opposite_term(mk_arith_geq(manager, t1, t2));
2667 }
2668
2669
2670 // b != 0 --> not (b == 0)
mk_arith_neq0(term_manager_t * manager,rba_buffer_t * b)2671 term_t mk_arith_neq0(term_manager_t *manager, rba_buffer_t *b) {
2672 return opposite_term(mk_arith_eq0(manager, b));
2673 }
2674
2675 // b <= 0 --> (- b) >= 0
mk_arith_leq0(term_manager_t * manager,rba_buffer_t * b)2676 term_t mk_arith_leq0(term_manager_t *manager, rba_buffer_t *b) {
2677 rba_buffer_negate(b);
2678 return mk_arith_geq0(manager, b);
2679 }
2680
2681 // b > 0 --> not (b <= 0)
mk_arith_gt0(term_manager_t * manager,rba_buffer_t * b)2682 term_t mk_arith_gt0(term_manager_t *manager, rba_buffer_t *b) {
2683 return opposite_term(mk_arith_leq0(manager, b));
2684 }
2685
2686 // b < 0 --> not (b >= 0)
mk_arith_lt0(term_manager_t * manager,rba_buffer_t * b)2687 term_t mk_arith_lt0(term_manager_t *manager, rba_buffer_t *b) {
2688 return opposite_term(mk_arith_geq0(manager, b));
2689 }
2690
2691
2692 /*
2693 * Variants: use a term t
2694 */
2695 // t == 0
mk_arith_term_eq0(term_manager_t * manager,term_t t)2696 term_t mk_arith_term_eq0(term_manager_t *manager, term_t t) {
2697 rba_buffer_t *b;
2698
2699 b = term_manager_get_arith_buffer(manager);
2700 reset_rba_buffer(b);
2701 rba_buffer_add_term(b, manager->terms, t);
2702
2703 return mk_arith_eq0(manager, b);
2704 }
2705
2706 // t != 0
mk_arith_term_neq0(term_manager_t * manager,term_t t)2707 term_t mk_arith_term_neq0(term_manager_t *manager, term_t t) {
2708 rba_buffer_t *b;
2709
2710 b = term_manager_get_arith_buffer(manager);
2711 reset_rba_buffer(b);
2712 rba_buffer_add_term(b, manager->terms, t);
2713
2714 return mk_arith_neq0(manager, b);
2715 }
2716
2717 // t >= 0
mk_arith_term_geq0(term_manager_t * manager,term_t t)2718 term_t mk_arith_term_geq0(term_manager_t *manager, term_t t) {
2719 rba_buffer_t *b;
2720
2721 b = term_manager_get_arith_buffer(manager);
2722 reset_rba_buffer(b);
2723 rba_buffer_add_term(b, manager->terms, t);
2724
2725 return mk_arith_geq0(manager, b);
2726 }
2727
2728 // t <= 0
mk_arith_term_leq0(term_manager_t * manager,term_t t)2729 term_t mk_arith_term_leq0(term_manager_t *manager, term_t t) {
2730 rba_buffer_t *b;
2731
2732 b = term_manager_get_arith_buffer(manager);
2733 reset_rba_buffer(b);
2734 rba_buffer_add_term(b, manager->terms, t);
2735
2736 return mk_arith_leq0(manager, b);
2737 }
2738
2739 // t > 0
mk_arith_term_gt0(term_manager_t * manager,term_t t)2740 term_t mk_arith_term_gt0(term_manager_t *manager, term_t t) {
2741 rba_buffer_t *b;
2742
2743 b = term_manager_get_arith_buffer(manager);
2744 reset_rba_buffer(b);
2745 rba_buffer_add_term(b, manager->terms, t);
2746
2747 return mk_arith_gt0(manager, b);
2748 }
2749
2750 // t < 0
mk_arith_term_lt0(term_manager_t * manager,term_t t)2751 term_t mk_arith_term_lt0(term_manager_t *manager, term_t t) {
2752 rba_buffer_t *b;
2753
2754 b = term_manager_get_arith_buffer(manager);
2755 reset_rba_buffer(b);
2756 rba_buffer_add_term(b, manager->terms, t);
2757
2758 return mk_arith_lt0(manager, b);
2759 }
2760
2761
2762 /*
2763 * Variant: use a term table
2764 */
2765 // b <= 0 --> (- b) >= 0
mk_direct_arith_leq0(term_table_t * tbl,rba_buffer_t * b,bool simplify_ite)2766 term_t mk_direct_arith_leq0(term_table_t *tbl, rba_buffer_t *b, bool simplify_ite) {
2767 rba_buffer_negate(b);
2768 return mk_direct_arith_geq0(tbl, b, simplify_ite);
2769 }
2770
2771 // b > 0 --> not (b <= 0)
mk_direct_arith_gt0(term_table_t * tbl,rba_buffer_t * b,bool simplify_ite)2772 term_t mk_direct_arith_gt0(term_table_t *tbl, rba_buffer_t *b, bool simplify_ite) {
2773 return opposite_term(mk_direct_arith_leq0(tbl, b, simplify_ite));
2774 }
2775
2776 // b < 0 --> not (b >= 0)
mk_direct_arith_lt0(term_table_t * tbl,rba_buffer_t * b,bool simplify_ite)2777 term_t mk_direct_arith_lt0(term_table_t *tbl, rba_buffer_t *b, bool simplify_ite) {
2778 return opposite_term(mk_direct_arith_geq0(tbl, b, simplify_ite));
2779 }
2780
2781
2782 /*
2783 * Make root atom.
2784 */
2785 static
mk_arith_root_atom_aux(term_table_t * terms,uint32_t k,term_t x,rba_buffer_t * p_b,root_atom_rel_t r,bool simplify_ite)2786 term_t mk_arith_root_atom_aux(term_table_t* terms, uint32_t k, term_t x, rba_buffer_t *p_b, root_atom_rel_t r, bool simplify_ite) {
2787 uint32_t degree = rba_buffer_degree(p_b);
2788 uint32_t degree_x = rba_buffer_var_degree(p_b, x);
2789 uint32_t n;
2790 rational_t root;
2791 term_t p, root_term, result = NULL_TERM;
2792 polynomial_t* p_poly;
2793
2794 (void)degree_x;
2795 assert(degree > 0);
2796 assert(k < degree_x);
2797
2798 if (degree == 1) {
2799 // Special case, these are just regular inequalities:
2800 // p = ax + b, solve p = 0, x = -b/a, resulting in x r -b/a
2801 n = p_b->nterms;
2802 assert(n > 0);
2803 if (n == 1) {
2804 // p = ax => root is 0
2805 // reuse p_b buffer for x
2806 reset_rba_buffer(p_b);
2807 switch (r) {
2808 case ROOT_ATOM_LT:
2809 rba_buffer_add_term(p_b, terms, x);
2810 result = mk_direct_arith_lt0(terms, p_b, simplify_ite);
2811 break;
2812 case ROOT_ATOM_LEQ:
2813 rba_buffer_add_term(p_b, terms, x);
2814 result = mk_direct_arith_leq0(terms, p_b, simplify_ite);
2815 break;
2816 case ROOT_ATOM_EQ:
2817 result = mk_arith_eq0_atom(terms, x, simplify_ite);
2818 break;
2819 case ROOT_ATOM_NEQ:
2820 result = mk_arith_eq0_atom(terms, x, simplify_ite);
2821 result = opposite_term(result);
2822 break;
2823 case ROOT_ATOM_GEQ:
2824 rba_buffer_add_term(p_b, terms, x);
2825 result = mk_direct_arith_geq0(terms, p_b, simplify_ite);
2826 break;
2827 case ROOT_ATOM_GT:
2828 rba_buffer_add_term(p_b, terms, x);
2829 result = mk_direct_arith_gt0(terms, p_b, simplify_ite);
2830 break;
2831 }
2832 } else {
2833 // p = ax + b => root is -b/a
2834 // we might still be multivariate, so have to check
2835 // we are degree 1, so we can have:
2836 // - one term, i.e. a*x
2837 // - two terms, i.e. a*x + b, but not a*x + b*y
2838 // - three terms or more is not univariate
2839 p = mk_direct_arith_term(terms, p_b);
2840 assert(term_kind(terms, p) == ARITH_POLY);
2841 p_poly = poly_term_desc(terms, p);
2842 if (p_poly->nterms <= 2) {
2843 if (p_poly->nterms == 1 || p_poly->mono[0].var == const_idx || p_poly->mono[1].var == const_idx) {
2844
2845 q_init(&root);
2846 if (p_poly->nterms == 2) {
2847 // ax + b
2848 if (p_poly->mono[0].var == const_idx) {
2849 q_set(&root, &p_poly->mono[0].coeff);
2850 q_div(&root, &p_poly->mono[1].coeff);
2851 } else {
2852 assert(p_poly->mono[1].var == const_idx);
2853 q_set(&root, &p_poly->mono[1].coeff);
2854 q_div(&root, &p_poly->mono[0].coeff);
2855 }
2856 q_neg(&root);
2857 } else {
2858 // ax, root = 0
2859 }
2860
2861 // reuse p_b buffer for x
2862 reset_rba_buffer(p_b);
2863
2864 switch (r) {
2865 case ROOT_ATOM_LT:
2866 rba_buffer_add_term(p_b, terms, x);
2867 rba_buffer_sub_const(p_b, &root);
2868 result = mk_direct_arith_lt0(terms, p_b, simplify_ite);
2869 break;
2870 case ROOT_ATOM_LEQ:
2871 rba_buffer_add_term(p_b, terms, x);
2872 rba_buffer_sub_const(p_b, &root);
2873 result = mk_direct_arith_leq0(terms, p_b, simplify_ite);
2874 break;
2875 case ROOT_ATOM_EQ:
2876 root_term = arith_constant(terms, &root);
2877 result = mk_arith_bineq_atom(terms, x, root_term, simplify_ite);
2878 break;
2879 case ROOT_ATOM_NEQ:
2880 root_term = arith_constant(terms, &root);
2881 result = mk_arith_bineq_atom(terms, x, root_term, simplify_ite);
2882 result = opposite_term(result);
2883 break;
2884 case ROOT_ATOM_GEQ:
2885 rba_buffer_add_term(p_b, terms, x);
2886 rba_buffer_sub_const(p_b, &root);
2887 result = mk_direct_arith_geq0(terms, p_b, simplify_ite);
2888 break;
2889 case ROOT_ATOM_GT:
2890 rba_buffer_add_term(p_b, terms, x);
2891 rba_buffer_sub_const(p_b, &root);
2892 result = mk_direct_arith_gt0(terms, p_b, simplify_ite);
2893 break;
2894 }
2895 } else {
2896 // not linear univariate
2897 result = arith_root_atom(terms, k, x, p, r);
2898 }
2899 } else {
2900 // not linear univariate
2901 result = arith_root_atom(terms, k, x, p, r);
2902 }
2903 }
2904 } else {
2905 term_t p = mk_direct_arith_term(terms, p_b);
2906 result = arith_root_atom(terms, k, x, p, r);
2907 }
2908
2909 return result;
2910 }
2911
mk_direct_arith_root_atom(rba_buffer_t * b,term_table_t * terms,uint32_t k,term_t x,term_t p,root_atom_rel_t r,bool simplify_ite)2912 term_t mk_direct_arith_root_atom(rba_buffer_t* b, term_table_t* terms, uint32_t k, term_t x, term_t p, root_atom_rel_t r, bool simplify_ite) {
2913 reset_rba_buffer(b);
2914 rba_buffer_add_term(b, terms, p);
2915 return mk_arith_root_atom_aux(terms, k, x, b, r, simplify_ite);
2916 }
2917
mk_arith_root_atom(term_manager_t * manager,uint32_t k,term_t x,term_t p,root_atom_rel_t r)2918 term_t mk_arith_root_atom(term_manager_t* manager, uint32_t k, term_t x, term_t p, root_atom_rel_t r) {
2919 rba_buffer_t *b;
2920 b = term_manager_get_arith_buffer(manager);
2921 return mk_direct_arith_root_atom(b, manager->terms, k, x, p, r, manager->simplify_ite);
2922 }
2923
mk_arith_root_atom_lt(term_manager_t * manager,uint32_t k,term_t x,term_t p)2924 term_t mk_arith_root_atom_lt(term_manager_t *manager, uint32_t k, term_t x, term_t p) {
2925 return mk_arith_root_atom(manager, k, x, p, ROOT_ATOM_LT);
2926 }
2927
mk_arith_root_atom_leq(term_manager_t * manager,uint32_t k,term_t x,term_t p)2928 term_t mk_arith_root_atom_leq(term_manager_t *manager, uint32_t k, term_t x, term_t p) {
2929 return mk_arith_root_atom(manager, k, x, p, ROOT_ATOM_LEQ);
2930 }
2931
mk_arith_root_atom_eq(term_manager_t * manager,uint32_t k,term_t x,term_t p)2932 term_t mk_arith_root_atom_eq(term_manager_t *manager, uint32_t k, term_t x, term_t p) {
2933 return mk_arith_root_atom(manager, k, x, p, ROOT_ATOM_EQ);
2934 }
2935
mk_arith_root_atom_neq(term_manager_t * manager,uint32_t k,term_t x,term_t p)2936 term_t mk_arith_root_atom_neq(term_manager_t *manager, uint32_t k, term_t x, term_t p) {
2937 return mk_arith_root_atom(manager, k, x, p, ROOT_ATOM_NEQ);
2938 }
2939
mk_arith_root_atom_gt(term_manager_t * manager,uint32_t k,term_t x,term_t p)2940 term_t mk_arith_root_atom_gt(term_manager_t *manager, uint32_t k, term_t x, term_t p) {
2941 return mk_arith_root_atom(manager, k, x, p, ROOT_ATOM_GT);
2942 }
2943
mk_arith_root_atom_geq(term_manager_t * manager,uint32_t k,term_t x,term_t p)2944 term_t mk_arith_root_atom_geq(term_manager_t *manager, uint32_t k, term_t x, term_t p) {
2945 return mk_arith_root_atom(manager, k, x, p, ROOT_ATOM_GEQ);
2946 }
2947
mk_direct_arith_root_atom_lt(rba_buffer_t * b,term_table_t * terms,uint32_t k,term_t x,term_t p,bool simplify_ite)2948 term_t mk_direct_arith_root_atom_lt(rba_buffer_t* b, term_table_t* terms, uint32_t k, term_t x, term_t p, bool simplify_ite) {
2949 return mk_direct_arith_root_atom(b, terms, k, x, p, ROOT_ATOM_LT, simplify_ite);
2950 }
2951
mk_direct_arith_root_atom_leq(rba_buffer_t * b,term_table_t * terms,uint32_t k,term_t x,term_t p,bool simplify_ite)2952 term_t mk_direct_arith_root_atom_leq(rba_buffer_t* b, term_table_t* terms, uint32_t k, term_t x, term_t p, bool simplify_ite) {
2953 return mk_direct_arith_root_atom(b, terms, k, x, p, ROOT_ATOM_LEQ, simplify_ite);
2954 }
2955
mk_direct_arith_root_atom_eq(rba_buffer_t * b,term_table_t * terms,uint32_t k,term_t x,term_t p,bool simplify_ite)2956 term_t mk_direct_arith_root_atom_eq(rba_buffer_t* b, term_table_t* terms, uint32_t k, term_t x, term_t p, bool simplify_ite) {
2957 return mk_direct_arith_root_atom(b, terms, k, x, p, ROOT_ATOM_EQ, simplify_ite);
2958 }
2959
2960 /*
2961 * ARITHMETIC FUNCTIONS
2962 */
2963
2964 /*
2965 * Auxiliary function: compute -t
2966 */
mk_arith_opposite(term_manager_t * manager,term_t t)2967 static term_t mk_arith_opposite(term_manager_t *manager, term_t t) {
2968 rba_buffer_t *b;
2969 term_table_t *tbl;
2970
2971 tbl = manager->terms;
2972 b = term_manager_get_arith_buffer(manager);
2973 reset_rba_buffer(b);
2974 rba_buffer_sub_term(b, tbl, t); // b := -t
2975 return arith_buffer_to_term(tbl, b);
2976 }
2977
2978 /*
2979 * Auxiliary function: compute 1/q * t
2980 */
mk_arith_div_by_constant(term_manager_t * manager,term_t t,const rational_t * q)2981 static term_t mk_arith_div_by_constant(term_manager_t *manager, term_t t, const rational_t *q) {
2982 rba_buffer_t *b;
2983 term_table_t *tbl;
2984
2985 assert(q_is_nonzero(q));
2986
2987 tbl = manager->terms;
2988 b = term_manager_get_arith_buffer(manager);
2989 reset_rba_buffer(b);
2990 rba_buffer_add_term(b, tbl, t); // b := t
2991 rba_buffer_div_const(b, q);
2992 return arith_buffer_to_term(tbl, b);
2993 }
2994
2995
2996 /*
2997 * Rational division: (/ t1 t2)
2998 *
2999 * Simplifications:
3000 * (/ t1 1) --> t1
3001 * (/ t1 -1) --> - t1
3002 * (/ t1 t2) --> (1/t2) * t1 if t2 is a non-zero constant
3003 *
3004 */
mk_arith_rdiv(term_manager_t * manager,term_t t1,term_t t2)3005 term_t mk_arith_rdiv(term_manager_t *manager, term_t t1, term_t t2) {
3006 term_table_t *tbl;
3007 rational_t *q;
3008 term_t t;
3009
3010 tbl = manager->terms;
3011 t = NULL_TERM;
3012
3013 if (term_kind(tbl, t2) == ARITH_CONSTANT) {
3014 q = rational_term_desc(tbl, t2);
3015 if (q_is_one(q)) {
3016 t = t1;
3017 } else if (q_is_minus_one(q)) {
3018 t = mk_arith_opposite(manager, t1);
3019 } else if (q_is_nonzero(q)) {
3020 t = mk_arith_div_by_constant(manager, t1, q); // q is safe to use here
3021 }
3022 }
3023
3024 // default
3025 if (t == NULL_TERM) {
3026 t = arith_rdiv(tbl, t1, t2);
3027 }
3028
3029 return t;
3030 }
3031
3032
3033 /*
3034 * (is_int t):
3035 *
3036 * Simplifications:
3037 * if t has type integer --> true
3038 * if t is a non-integer term --> false
3039 * (is_int (abs t)) --> (is_int t)
3040 *
3041 * Could do more with polynomials
3042 */
mk_arith_is_int(term_manager_t * manager,term_t t)3043 term_t mk_arith_is_int(term_manager_t *manager, term_t t) {
3044 term_table_t *tbl;
3045
3046 tbl = manager->terms;
3047 if (is_integer_term(tbl, t)) {
3048 return true_term;
3049 }
3050 if (arith_term_is_not_integer(tbl, t)) {
3051 return false_term;
3052 }
3053
3054 switch (term_kind(tbl, t)) {
3055 case ARITH_ABS:
3056 t = arith_abs_arg(tbl, t);
3057 break;
3058
3059 // MORE TO BE DONE
3060 default:
3061 break;
3062 }
3063
3064 return arith_is_int(tbl, t);
3065 }
3066
3067 /*
3068 * (abs t):
3069 *
3070 * Simplifications:
3071 * - if t is known to be non-negative --> t
3072 * - if t is known to be negative --> (- t)
3073 * - the first rule ensures (abs (abs t)) --> (abs t)
3074 */
mk_arith_abs(term_manager_t * manager,term_t t)3075 term_t mk_arith_abs(term_manager_t *manager, term_t t) {
3076 term_table_t *tbl;
3077
3078 tbl = manager->terms;
3079
3080 if (arith_term_is_nonneg(tbl, t, manager->simplify_ite)) return t;
3081
3082 if (arith_term_is_nonpos(tbl, t, manager->simplify_ite)) return mk_arith_opposite(manager, t);
3083
3084 return arith_abs(tbl, t);
3085 }
3086
3087
3088 /*
3089 * (floor t) and (ceil t)
3090 * - if t is an integer --> t
3091 * - otherwise, build the term.
3092 *
3093 * Could do more: rewrite t as <integer> + <rest> then
3094 * (floor t) = <integer> + (floor <rest>)
3095 * (ceil t) = <integer> + (ceil <rest>)
3096 * Not clear whether that would help.
3097 */
mk_arith_floor(term_manager_t * manager,term_t t)3098 term_t mk_arith_floor(term_manager_t *manager, term_t t) {
3099 term_table_t *tbl;
3100
3101 tbl = manager->terms;
3102 if (is_integer_term(tbl, t)) return t;
3103
3104 return arith_floor(tbl, t);
3105 }
3106
mk_arith_ceil(term_manager_t * manager,term_t t)3107 term_t mk_arith_ceil(term_manager_t *manager, term_t t) {
3108 term_table_t *tbl;
3109
3110 tbl = manager->terms;
3111 if (is_integer_term(tbl, t)) return t;
3112
3113 return arith_ceil(manager->terms, t);
3114 }
3115
3116
3117 /*
3118 * DIV and MOD
3119 *
3120 * Intended semantics for div and mod:
3121 * - if y > 0 then div(x, y) is floor(x/y)
3122 * - if y < 0 then div(x, y) is ceil(x/y)
3123 * - 0 <= rem(x, y) < y
3124 * - x = y * div(x, y) + rem(x, y)
3125 * These operations are defined for any x and non-zero y.
3126 * The terms x and y are not required to be integers.
3127 */
3128
3129 /*
3130 * Division and mod of two rationals
3131 * - q2 is the divisor
3132 */
arith_constant_div(term_manager_t * manager,rational_t * q1,rational_t * q2)3133 static term_t arith_constant_div(term_manager_t *manager, rational_t *q1, rational_t *q2) {
3134 rational_t *aux;
3135
3136 aux = &manager->r0;
3137 q_smt2_div(aux, q1, q2);
3138 q_normalize(aux);
3139
3140 return arith_constant(manager->terms, aux);
3141 }
3142
arith_constant_mod(term_manager_t * manager,rational_t * q1,rational_t * q2)3143 static term_t arith_constant_mod(term_manager_t *manager, rational_t *q1, rational_t *q2) {
3144 rational_t *aux;
3145
3146 aux = &manager->r0;
3147 q_smt2_mod(aux, q1, q2);
3148 q_normalize(aux);
3149
3150 return arith_constant(manager->terms, aux);
3151 }
3152
3153
3154 /*
3155 * Integer division and mod
3156 *
3157 * Simplifications:
3158 * (div x 1) --> x if x is an integer
3159 * (div x -1) --> - x if x is an integer
3160 *
3161 * (mod x 1) --> 0 if x is an integer
3162 * (mod x -1) --> 0 if x is an integer
3163 */
mk_arith_idiv(term_manager_t * manager,term_t t1,term_t t2)3164 term_t mk_arith_idiv(term_manager_t *manager, term_t t1, term_t t2) {
3165 term_table_t *tbl;
3166 rational_t *q;
3167 term_t t;
3168
3169 tbl = manager->terms;
3170
3171 t = NULL_TERM;
3172
3173 // Special cases
3174 if (term_kind(tbl, t2) == ARITH_CONSTANT) {
3175 q = rational_term_desc(tbl, t2);
3176 if (q_is_nonzero(q)) {
3177 if (q_is_one(q) && is_integer_term(tbl, t1)) {
3178 t = t1;
3179 } else if (q_is_minus_one(q) && is_integer_term(tbl, t1)) {
3180 t = mk_arith_opposite(manager, t1); // - t1
3181 } else if (term_kind(tbl, t1) == ARITH_CONSTANT) {
3182 t = arith_constant_div(manager, rational_term_desc(tbl, t1), q);
3183 }
3184 }
3185 }
3186
3187 // Default case
3188 if (t == NULL_TERM) {
3189 t = arith_idiv(tbl, t1, t2);
3190 }
3191
3192 return t;
3193 }
3194
mk_arith_mod(term_manager_t * manager,term_t t1,term_t t2)3195 term_t mk_arith_mod(term_manager_t *manager, term_t t1, term_t t2) {
3196 term_table_t *tbl;
3197 rational_t *q;
3198 term_t t;
3199
3200 tbl = manager->terms;
3201
3202 t = NULL_TERM;
3203
3204 // Special case
3205 if (term_kind(tbl, t2) == ARITH_CONSTANT) {
3206 q = rational_term_desc(tbl, t2);
3207 if (q_is_nonzero(q)) {
3208 if ((q_is_one(q) || q_is_minus_one(q)) && is_integer_term(tbl, t1)) {
3209 t = zero_term;
3210 } else if (term_kind(tbl, t1) == ARITH_CONSTANT) {
3211 t = arith_constant_mod(manager, rational_term_desc(tbl, t1), q);
3212 }
3213 }
3214 }
3215
3216 if (t == NULL_TERM) {
3217 t = arith_mod(tbl, t1, t2);
3218 }
3219
3220 return t;
3221 }
3222
3223
3224 /*
3225 * DIVISIBILITY TEST
3226 */
3227
3228 /*
3229 * Force divisor to be positive: build -q
3230 */
neg_rational(term_manager_t * manager,rational_t * q)3231 static term_t neg_rational(term_manager_t *manager, rational_t *q) {
3232 rational_t *aux;
3233
3234 aux = &manager->r0;
3235 q_set_neg(aux, q);
3236 q_normalize(aux);
3237
3238 return arith_constant(manager->terms, aux);
3239 }
3240
3241 /*
3242 * t1 must be a rational constant
3243 *
3244 * Simplifications:
3245 * (divides 0 t2) ---> (t2 == 0)
3246 * (divides 1 t2) ---> (is_int t2)
3247 * (divides -1 t2) ---> (is_int t2)
3248 *
3249 * If t1 is negative:
3250 * (divides t1 t2) ---> (divides (- t1) t2)
3251 */
mk_arith_divides(term_manager_t * manager,term_t t1,term_t t2)3252 term_t mk_arith_divides(term_manager_t *manager, term_t t1, term_t t2) {
3253 term_table_t *tbl;
3254 rational_t *q;
3255 term_t t;
3256
3257 tbl = manager->terms;
3258 assert(term_kind(tbl, t1) == ARITH_CONSTANT);
3259
3260 q = rational_term_desc(tbl, t1);
3261
3262 if (q_is_zero(q)) {
3263 t = mk_arith_eq0_atom(tbl, t2, manager->simplify_ite);
3264 } else if (q_is_one(q) || q_is_minus_one(q)) {
3265 t = mk_arith_is_int(manager, t2);
3266 } else {
3267
3268 switch (term_kind(tbl, t2)) {
3269 case ARITH_CONSTANT:
3270 t = false_term;
3271 if (q_divides(q, rational_term_desc(tbl, t2))) {
3272 t = true_term;
3273 }
3274 break;
3275
3276 default:
3277 // force t1 to be positive
3278 if (q_is_neg(q)) {
3279 t1 = neg_rational(manager, q);
3280 }
3281 t = arith_divides(tbl, t1, t2);
3282 break;
3283 }
3284 }
3285
3286 return t;
3287 }
3288
mk_direct_arith_root_atom_neq(rba_buffer_t * b,term_table_t * terms,uint32_t k,term_t x,term_t p,bool simplify_ite)3289 term_t mk_direct_arith_root_atom_neq(rba_buffer_t* b, term_table_t* terms, uint32_t k, term_t x, term_t p, bool simplify_ite) {
3290 return mk_direct_arith_root_atom(b, terms, k, x, p, ROOT_ATOM_NEQ, simplify_ite);
3291 }
3292
mk_direct_arith_root_atom_gt(rba_buffer_t * b,term_table_t * terms,uint32_t k,term_t x,term_t p,bool simplify_ite)3293 term_t mk_direct_arith_root_atom_gt(rba_buffer_t* b, term_table_t* terms, uint32_t k, term_t x, term_t p, bool simplify_ite) {
3294 return mk_direct_arith_root_atom(b, terms, k, x, p, ROOT_ATOM_GT, simplify_ite);
3295 }
3296
mk_direct_arith_root_atom_geq(rba_buffer_t * b,term_table_t * terms,uint32_t k,term_t x,term_t p,bool simplify_ite)3297 term_t mk_direct_arith_root_atom_geq(rba_buffer_t* b, term_table_t* terms, uint32_t k, term_t x, term_t p, bool simplify_ite) {
3298 return mk_direct_arith_root_atom(b, terms, k, x, p, ROOT_ATOM_GEQ, simplify_ite);
3299 }
3300
3301
3302 /****************
3303 * EQUALITIES *
3304 ***************/
3305
3306 /*
3307 * Bitvector equality and disequality
3308 */
mk_bveq(term_manager_t * manager,term_t t1,term_t t2)3309 term_t mk_bveq(term_manager_t *manager, term_t t1, term_t t2) {
3310 return mk_bitvector_eq(manager, t1, t2);
3311 }
3312
mk_bvneq(term_manager_t * manager,term_t t1,term_t t2)3313 term_t mk_bvneq(term_manager_t *manager, term_t t1, term_t t2) {
3314 return opposite_term(mk_bitvector_eq(manager, t1, t2));
3315 }
3316
3317
3318 /*
3319 * Generic equality: convert to boolean, arithmetic, or bitvector equality
3320 */
mk_eq(term_manager_t * manager,term_t t1,term_t t2)3321 term_t mk_eq(term_manager_t *manager, term_t t1, term_t t2) {
3322 term_table_t *tbl;
3323 term_t aux;
3324
3325 tbl = manager->terms;
3326
3327 if (is_boolean_term(tbl, t1)) {
3328 assert(is_boolean_term(tbl, t2));
3329 return mk_iff(manager, t1, t2);
3330 }
3331
3332 if (is_arithmetic_term(tbl, t1)) {
3333 assert(is_arithmetic_term(tbl, t2));
3334 return mk_arith_eq(manager, t1, t2);
3335 }
3336
3337 if (is_bitvector_term(tbl, t1)) {
3338 assert(is_bitvector_term(tbl, t2));
3339 return mk_bveq(manager, t1, t2);
3340 }
3341
3342 // general case
3343 if (t1 == t2) return true_term;
3344 if (disequal_terms(tbl, t1, t2, manager->simplify_ite)) {
3345 return false_term;
3346 }
3347
3348 // put smaller index on the left
3349 if (t1 > t2) {
3350 aux = t1; t1 = t2; t2 = aux;
3351 }
3352
3353 return eq_term(tbl, t1, t2);
3354 }
3355
3356
3357 /*
3358 * Generic disequality.
3359 *
3360 * We don't want to return (not mk_eq(manager, t1, t2)) because
3361 * that could miss some simplifications if t1 and t2 are Boolean.
3362 */
mk_neq(term_manager_t * manager,term_t t1,term_t t2)3363 term_t mk_neq(term_manager_t *manager, term_t t1, term_t t2) {
3364 term_table_t *tbl;
3365 term_t aux;
3366
3367 tbl = manager->terms;
3368
3369 if (is_boolean_term(tbl, t1)) {
3370 assert(is_boolean_term(tbl, t2));
3371 return mk_binary_xor(manager, t1, t2);
3372 }
3373
3374 if (is_arithmetic_term(tbl, t1)) {
3375 assert(is_arithmetic_term(tbl, t2));
3376 return mk_arith_neq(manager, t1, t2);
3377 }
3378
3379 if (is_bitvector_term(tbl, t1)) {
3380 assert(is_bitvector_term(tbl, t2));
3381 return mk_bvneq(manager, t1, t2);
3382 }
3383
3384 // general case
3385 if (t1 == t2) return false_term;
3386 if (disequal_terms(tbl, t1, t2, manager->simplify_ite)) {
3387 return true_term;
3388 }
3389
3390 // put smaller index on the left
3391 if (t1 > t2) {
3392 aux = t1; t1 = t2; t2 = aux;
3393 }
3394
3395 return opposite_term(eq_term(tbl, t1, t2));
3396 }
3397
3398
3399 /*
3400 * Array disequality:
3401 * - given two arrays a and b of n terms, build the term
3402 * (or (/= a[0] b[0]) ... (/= a[n-1] b[n-1]))
3403 */
mk_array_neq(term_manager_t * manager,uint32_t n,const term_t a[],const term_t b[])3404 term_t mk_array_neq(term_manager_t *manager, uint32_t n, const term_t a[], const term_t b[]) {
3405 uint32_t i;
3406 term_t *aux;
3407
3408 resize_ivector(&manager->vector0, n);
3409 aux = manager->vector0.data;
3410
3411 for (i=0; i<n; i++) {
3412 aux[i] = mk_neq(manager, a[i], b[i]);
3413 }
3414 return mk_or(manager, n, aux);
3415 }
3416
3417
3418 /*
3419 * Array equality:
3420 * - given two arrays a and b of n term, build
3421 * (and (= a[0] b[0]) ... (= a[n-1] b[n-1])
3422 */
mk_array_eq(term_manager_t * manager,uint32_t n,const term_t a[],const term_t b[])3423 term_t mk_array_eq(term_manager_t *manager, uint32_t n, const term_t a[], const term_t b[]) {
3424 return opposite_term(mk_array_neq(manager, n, a, b));
3425 }
3426
3427
3428
3429
3430 /*****************************
3431 * GENERIC CONSTRUCTORS *
3432 ****************************/
3433
3434 /*
3435 * When constructing a term of singleton type tau, we return the
3436 * representative for tau (except for variables).
3437 */
3438
3439 /*
3440 * Constant of type tau and index i
3441 * - tau must be uninterpreted or scalar type
3442 * - i must be non-negative and smaller than the size of tau
3443 * (which matters only if tau is scalar)
3444 */
mk_constant(term_manager_t * manager,type_t tau,int32_t i)3445 term_t mk_constant(term_manager_t *manager, type_t tau, int32_t i) {
3446 term_t t;
3447
3448 assert(i >= 0);
3449 t = constant_term(manager->terms, tau, i);
3450 if (is_unit_type(manager->types, tau)) {
3451 store_unit_type_rep(manager->terms, tau, t);
3452 }
3453
3454 return t;
3455 }
3456
3457
3458 /*
3459 * New uninterpreted term of type tau
3460 * - i.e., this creates a fresh global variable
3461 */
mk_uterm(term_manager_t * manager,type_t tau)3462 term_t mk_uterm(term_manager_t *manager, type_t tau) {
3463 if (is_unit_type(manager->types, tau)) {
3464 return get_unit_type_rep(manager->terms, tau);
3465 }
3466
3467 return new_uninterpreted_term(manager->terms, tau);
3468 }
3469
3470
3471 /*
3472 * New variable of type tau
3473 * - this creates a fresh variable (for quantifiers)
3474 */
mk_variable(term_manager_t * manager,type_t tau)3475 term_t mk_variable(term_manager_t *manager, type_t tau) {
3476 return new_variable(manager->terms, tau);
3477 }
3478
3479
3480
3481 /*
3482 * Function application:
3483 * - fun must have arity n
3484 * - arg = array of n arguments
3485 * - the argument types much match the domain of f
3486 *
3487 * Simplifications if fun is an update term:
3488 * ((update f (a_1 ... a_n) v) a_1 ... a_n) --> v
3489 * ((update f (a_1 ... a_n) v) x_1 ... x_n) --> (f x_1 ... x_n)
3490 * if x_i must disequal a_i
3491 *
3492 */
mk_application(term_manager_t * manager,term_t fun,uint32_t n,const term_t arg[])3493 term_t mk_application(term_manager_t *manager, term_t fun, uint32_t n, const term_t arg[]) {
3494 term_table_t *tbl;
3495 type_table_t *types;
3496 composite_term_t *update;
3497 type_t tau;
3498
3499 tbl = manager->terms;
3500 types = manager->types;
3501
3502 // singleton function type
3503 tau = term_type(tbl, fun);
3504 if (is_unit_type(types, tau)) {
3505 return get_unit_type_rep(tbl, function_type_range(types, tau));
3506 }
3507
3508 while (term_kind(tbl, fun) == UPDATE_TERM) {
3509 // fun is (update f (a_1 ... a_n) v)
3510 update = update_term_desc(tbl, fun);
3511 assert(update->arity == n+2);
3512
3513 /*
3514 * update->arg[0] is f
3515 * update->arg[1] to update->arg[n] = a_1 to a_n
3516 * update->arg[n+1] is v
3517 */
3518 if (equal_term_arrays(n, update->arg + 1, arg)) {
3519 return update->arg[n+1];
3520 }
3521
3522 if (disequal_term_arrays(tbl, n, update->arg + 1, arg, manager->simplify_ite)) {
3523 // ((update f (a_1 ... a_n) v) x_1 ... x_n) ---> (f x_1 ... x_n)
3524 // repeat simplification if f is an update term again
3525 fun = update->arg[0];
3526 } else {
3527 break;
3528 }
3529 }
3530
3531 return app_term(tbl, fun, n, arg);
3532 }
3533
3534
3535
3536 /*
3537 * Attempt to simplify (mk-tuple arg[0] .... arg[n-1]):
3538 * return x if arg[i] = (select i x) for i=0 ... n-1 and x is a tuple term of arity n
3539 * return NULL_TERM otherwise
3540 */
simplify_mk_tuple(term_table_t * tbl,uint32_t n,const term_t arg[])3541 static term_t simplify_mk_tuple(term_table_t *tbl, uint32_t n, const term_t arg[]) {
3542 uint32_t i;
3543 term_t x, a;
3544
3545 a = arg[0];
3546 if (is_neg_term(a) ||
3547 term_kind(tbl, a) != SELECT_TERM ||
3548 select_term_index(tbl, a) != 0) {
3549 return NULL_TERM;
3550 }
3551
3552 // arg[0] is (select 0 x)
3553 x = select_term_arg(tbl, a);
3554 if (tuple_type_arity(tbl->types, term_type(tbl, x)) != n) {
3555 // x does not have arity n
3556 return NULL_TERM;
3557 }
3558
3559 for (i = 1; i<n; i++) {
3560 a = arg[i];
3561 if (is_neg_term(a) ||
3562 term_kind(tbl, a) != SELECT_TERM ||
3563 select_term_index(tbl, a) != i ||
3564 select_term_arg(tbl, a) != x) {
3565 // arg[i] is not (select i x)
3566 return NULL_TERM;
3567 }
3568 }
3569
3570 return x;
3571 }
3572
3573
3574 /*
3575 * Tuple constructor:
3576 * - arg = array of n terms
3577 * - n must be positive and no more than YICES_MAX_ARITY
3578 *
3579 * Simplification:
3580 * (mk_tuple (select 0 x) ... (select n-1 x)) --> x
3581 * provided x is a tuple of arity n
3582 */
mk_tuple(term_manager_t * manager,uint32_t n,const term_t arg[])3583 term_t mk_tuple(term_manager_t *manager, uint32_t n, const term_t arg[]) {
3584 term_table_t *tbl;
3585 term_t x;
3586 type_t tau;
3587
3588 tbl = manager->terms;
3589 x = simplify_mk_tuple(tbl, n, arg);
3590 if (x == NULL_TERM) {
3591 // not simplified
3592 x = tuple_term(tbl, n, arg);
3593
3594 // check whether x is unique element of its type
3595 tau = term_type(tbl, x);
3596 if (is_unit_type(manager->types, tau)) {
3597 store_unit_type_rep(tbl, tau, x);
3598 }
3599 }
3600
3601 return x;
3602 }
3603
3604
3605 /*
3606 * Projection: component i of tuple.
3607 * - tuple must have tuple type
3608 * - i must be between 0 and the number of components in the tuple
3609 * type - 1
3610 *
3611 * Simplification: (select i (mk_tuple x_1 ... x_n)) --> x_i
3612 */
mk_select(term_manager_t * manager,uint32_t index,term_t tuple)3613 term_t mk_select(term_manager_t *manager, uint32_t index, term_t tuple) {
3614 term_table_t *tbl;
3615 type_table_t *types;
3616 type_t tau;
3617 term_t x;
3618
3619 // simplify
3620 if (term_kind(manager->terms, tuple) == TUPLE_TERM) {
3621 x = composite_term_arg(manager->terms, tuple, index);
3622 } else {
3623 // check for singleton type
3624 tbl = manager->terms;
3625 types = manager->types;
3626 tau = term_type(tbl, tuple);
3627 tau = tuple_type_component(types, tau, index);
3628
3629 if (is_unit_type(types, tau)) {
3630 x = get_unit_type_rep(tbl, tau);
3631 } else {
3632 x = select_term(tbl, index, tuple);
3633 }
3634 }
3635
3636 return x;
3637 }
3638
3639
3640 /*
3641 * Function update: (update f (arg[0] ... arg[n-1]) new_v)
3642 * - f must have function type and arity n
3643 * - new_v's type must be a subtype of f's range
3644 *
3645 * Simplifications:
3646 * (update (update f (a_1 ... a_n) v) (a_1 ... a_n) v') --> (update f (a_1 ... a_n) v')
3647 * (update f (a_1 ... a_n) (f a_1 ... a_n)) --> f
3648 */
mk_update(term_manager_t * manager,term_t fun,uint32_t n,const term_t arg[],term_t new_v)3649 term_t mk_update(term_manager_t *manager, term_t fun, uint32_t n, const term_t arg[], term_t new_v) {
3650 term_table_t *tbl;
3651 composite_term_t *update, *app;
3652 type_t tau;
3653
3654 tbl = manager->terms;
3655
3656 // singleton function type
3657 tau = term_type(tbl, fun);
3658 if (is_unit_type(manager->types, tau)) {
3659 assert(unit_type_rep(tbl, tau) == fun);
3660 return fun;
3661 }
3662
3663 // try simplification
3664 while (term_kind(tbl, fun) == UPDATE_TERM) {
3665 // fun is (update f b_1 ... b_n v)
3666 update = update_term_desc(tbl, fun);
3667 assert(update->arity == n+2);
3668
3669 if (equal_term_arrays(n, update->arg + 1, arg)) {
3670 // b_1 = a_1, ..., b_n = a_n so
3671 // (update (update fun b_1 ... b_n v0) a_1 ... a_n new_v)) --> (update fun (a_1 ... a_n) new_v)
3672 fun = update->arg[0];
3673 } else {
3674 break;
3675 }
3676 }
3677
3678 // build (update fun a_1 .. a_n new_v): try second simplification
3679 if (term_kind(tbl, new_v) == APP_TERM) {
3680 app = app_term_desc(tbl, new_v);
3681 if (app->arity == n+1 && app->arg[0] == fun &&
3682 equal_term_arrays(n, app->arg + 1, arg)) {
3683 // new_v is (apply fun a_1 ... a_n)
3684 return fun;
3685 }
3686 }
3687
3688 return update_term(tbl, fun, n, arg, new_v);
3689 }
3690
3691
3692
3693 /*
3694 * Distinct: all terms arg[0] ... arg[n-1] must have compatible types
3695 * - n must be positive and no more than YICES_MAX_ARITY
3696 *
3697 * (distinct t1 ... t_n):
3698 *
3699 * if n == 1 --> true
3700 * if n == 2 --> (diseq t1 t2)
3701 * if t_i and t_j are equal --> false
3702 * if all are disequal --> true
3703 *
3704 * More simplifications uses type information,
3705 * (distinct f g h) --> false if f g h are boolean.
3706 */
mk_distinct(term_manager_t * manager,uint32_t n,term_t arg[])3707 term_t mk_distinct(term_manager_t *manager, uint32_t n, term_t arg[]) {
3708 uint32_t i;
3709 type_t tau;
3710
3711 if (n == 1) {
3712 return true_term;
3713 }
3714
3715 if (n == 2) {
3716 return mk_neq(manager, arg[0], arg[1]);
3717 }
3718
3719 // check for finite types
3720 tau = term_type(manager->terms, arg[0]);
3721 if (type_card(manager->types, tau) < n && type_card_is_exact(manager->types, tau)) {
3722 // card exact implies that tau is finite (and small)
3723 return false_term;
3724 }
3725
3726
3727 // check if two of the terms are equal
3728 int_array_sort(arg, n);
3729 for (i=1; i<n; i++) {
3730 if (arg[i] == arg[i-1]) {
3731 return false_term;
3732 }
3733 }
3734
3735 // WARNING: THIS CAN BE EXPENSIVE
3736 if (pairwise_disequal_terms(manager->terms, n, arg, manager->simplify_ite)) {
3737 return true_term;
3738 }
3739
3740 return distinct_term(manager->terms, n, arg);
3741 }
3742
3743
3744 /*
3745 * (tuple-update tuple index new_v) is (tuple with component i set to new_v)
3746 *
3747 * If new_v is (select t i) then
3748 * (tuple-update t i v) is t
3749 *
3750 * If tuple is (mk-tuple x_0 ... x_i ... x_n-1) then
3751 * (tuple-update t i v) is (mk-tuple x_0 ... v ... x_n-1)
3752 *
3753 * Otherwise,
3754 * (tuple-update t i v) is (mk-tuple (select t 0) ... v ... (select t n-1))
3755 *
3756 */
mk_tuple_aux(term_manager_t * manager,term_t tuple,uint32_t n,uint32_t i,term_t v)3757 static term_t mk_tuple_aux(term_manager_t *manager, term_t tuple, uint32_t n, uint32_t i, term_t v) {
3758 term_table_t *tbl;
3759 composite_term_t *desc;
3760 term_t *a;
3761 term_t t;
3762 uint32_t j;
3763
3764 tbl = manager->terms;
3765
3766 if (is_pos_term(v) && term_kind(tbl, v) == SELECT_TERM &&
3767 select_term_arg(tbl, v) == tuple && select_term_index(tbl, v) == i) {
3768 return tuple;
3769 }
3770
3771 // use vector0 as buffer:
3772 resize_ivector(&manager->vector0, n);
3773 a = manager->vector0.data;
3774
3775 if (term_kind(tbl, tuple) == TUPLE_TERM) {
3776 desc = tuple_term_desc(tbl, tuple);
3777 for (j=0; j<n; j++) {
3778 if (i == j) {
3779 a[j] = v;
3780 } else {
3781 a[j] = desc->arg[j];
3782 }
3783 }
3784 } else {
3785 for (j=0; j<n; j++) {
3786 if (i == j) {
3787 a[j] = v;
3788 } else {
3789 a[j] = select_term(tbl, j, tuple);
3790 }
3791 }
3792 }
3793
3794 t = tuple_term(tbl, n, a);
3795
3796 // cleanup
3797 ivector_reset(&manager->vector0);
3798
3799 return t;
3800 }
3801
3802
3803 /*
3804 * Tuple update: replace component i of tuple by new_v
3805 */
mk_tuple_update(term_manager_t * manager,term_t tuple,uint32_t index,term_t new_v)3806 term_t mk_tuple_update(term_manager_t *manager, term_t tuple, uint32_t index, term_t new_v) {
3807 uint32_t n;
3808 type_t tau;
3809
3810 // singleton type
3811 tau = term_type(manager->terms, tuple);
3812 if (is_unit_type(manager->types, tau)) {
3813 assert(unit_type_rep(manager->terms, tau) == tuple);
3814 return tuple;
3815 }
3816
3817 n = tuple_type_arity(manager->types, tau);
3818 return mk_tuple_aux(manager, tuple, n, index, new_v);
3819 }
3820
3821
3822
3823 /*
3824 * Quantifiers:
3825 * - n = number of variables (n must be positive and no more than YICES_MAX_VAR)
3826 * - all variables v[0 ... n-1] must be distinct
3827 * - body must be a Boolean term
3828 *
3829 * Simplification
3830 * (forall (x_1::t_1 ... x_n::t_n) true) --> true
3831 * (forall (x_1::t_1 ... x_n::t_n) false) --> false (types are nonempty)
3832 *
3833 * (exists (x_1::t_1 ... x_n::t_n) true) --> true
3834 * (exists (x_1::t_1 ... x_n::t_n) false) --> false (types are nonempty)
3835 */
mk_forall(term_manager_t * manager,uint32_t n,const term_t var[],term_t body)3836 term_t mk_forall(term_manager_t *manager, uint32_t n, const term_t var[], term_t body) {
3837 if (body == true_term) return body;
3838 if (body == false_term) return body;
3839
3840 return forall_term(manager->terms, n, var, body);
3841 }
3842
mk_exists(term_manager_t * manager,uint32_t n,const term_t var[],term_t body)3843 term_t mk_exists(term_manager_t *manager, uint32_t n, const term_t var[], term_t body) {
3844 if (body == true_term) return body;
3845 if (body == false_term) return body;
3846
3847 // (not (forall ... (not body))
3848 return opposite_term(forall_term(manager->terms, n, var, opposite_term(body)));
3849 }
3850
3851
3852
3853 /*
3854 * Lambda term:
3855 * - n = number of variables
3856 * - var[0 .. n-1] = variables (must all be distinct)
3857 *
3858 * Simplification:
3859 * (lambda (x_1::t_1 ... x_n::t_n) (f x_1 ... x_n)) --> f
3860 *
3861 * provided f has type [t_1 ... t_n --> sigma]
3862 */
3863
3864 // check whether var[0 ... n-1] and arg[0 ... n-1] are equal
equal_arrays(const term_t var[],const term_t arg[],uint32_t n)3865 static bool equal_arrays(const term_t var[], const term_t arg[], uint32_t n) {
3866 uint32_t i;
3867
3868 for (i=0; i<n; i++) {
3869 if (var[i] != arg[i]) {
3870 return false;
3871 }
3872 }
3873
3874 return true;
3875 }
3876
3877 // check whether the domain of f matches the variable types
same_domain(term_table_t * table,term_t f,const term_t var[],uint32_t n)3878 static bool same_domain(term_table_t *table, term_t f, const term_t var[], uint32_t n) {
3879 function_type_t *desc;
3880 type_t tau;
3881 uint32_t i;
3882
3883 tau = term_type(table, f);
3884 desc = function_type_desc(table->types, tau);
3885 assert(desc->ndom == n);
3886
3887 for (i=0; i<n; i++) {
3888 if (desc->domain[i] != term_type(table, var[i])) {
3889 return false;
3890 }
3891 }
3892
3893 return true;
3894 }
3895
mk_lambda(term_manager_t * manager,uint32_t n,const term_t var[],term_t body)3896 term_t mk_lambda(term_manager_t *manager, uint32_t n, const term_t var[], term_t body) {
3897 term_table_t *tbl;
3898 composite_term_t *d;
3899 term_t f;
3900
3901 assert(0 < n && n <= YICES_MAX_ARITY);
3902
3903 tbl = manager->terms;
3904 if (is_pos_term(body) && term_kind(tbl, body) == APP_TERM) {
3905 d = app_term_desc(tbl, body);
3906 if (d->arity == n+1 && equal_arrays(var, d->arg + 1, n)) {
3907 f = d->arg[0];
3908 if (same_domain(tbl, f, var, n)) {
3909 return f;
3910 }
3911 }
3912 }
3913
3914 return lambda_term(manager->terms, n, var, body);
3915 }
3916
3917
3918
3919
3920 /*************************
3921 * BITVECTOR CONSTANTS *
3922 ************************/
3923
3924 /*
3925 * Convert b to a bitvector constant
3926 * - normalize b first
3927 * - b->bitsize must be positive and no more than YICES_MAX_BVSIZE
3928 * - depending on b->bitsize, this either builds a bv64 constant
3929 * or a wide bvconst term (more than 64 bits)
3930 */
mk_bv_constant(term_manager_t * manager,bvconstant_t * b)3931 term_t mk_bv_constant(term_manager_t *manager, bvconstant_t *b) {
3932 uint32_t n;
3933 uint64_t x;
3934 term_t t;
3935
3936 assert(b->bitsize > 0);
3937
3938 n = b->bitsize;
3939 bvconst_normalize(b->data, n); // reduce modulo 2^n
3940
3941 if (n <= 64) {
3942 if (n <= 32) {
3943 x = bvconst_get32(b->data);
3944 } else {
3945 x = bvconst_get64(b->data);
3946 }
3947 t = bv64_constant(manager->terms, n, x);
3948 } else {
3949 t = bvconst_term(manager->terms, n, b->data);
3950 }
3951
3952 return t;
3953 }
3954
3955
3956
3957 /**************************
3958 * CONVERT BITS TO TERMS *
3959 *************************/
3960
3961 /*
3962 * A bvlogic buffer stores an array of bits in manager->nodes.
3963 * Function bvlogic_buffer_get_bvarray requires converting bits
3964 * back to Boolean terms.
3965 *
3966 * The nodes data structure is defined in bit_expr.h
3967 */
3968
3969 /*
3970 * Recursive function: return the term mapped to node x
3971 * - compute it if needed then store the result in manager->nodes->map[x]
3972 */
3973 static term_t map_node_to_term(term_manager_t *manager, node_t x);
3974
3975 /*
3976 * Get the term mapped to bit b. If node_of(b) is mapped to t then
3977 * - if b has positive polarity, map_of(b) = t
3978 * - if b has negative polarity, map_of(b) = not t
3979 */
map_bit_to_term(term_manager_t * manager,bit_t b)3980 static inline term_t map_bit_to_term(term_manager_t *manager, bit_t b) {
3981 return map_node_to_term(manager, node_of_bit(b)) ^ polarity_of(b);
3982 }
3983
3984
3985
3986 /*
3987 * Given two bits b1 = c[0] and b2 = c[1], convert (or b1 b2) to a term
3988 */
make_or2(term_manager_t * manager,bit_t * c)3989 static term_t make_or2(term_manager_t *manager, bit_t *c) {
3990 term_t x, y;
3991
3992 x = map_bit_to_term(manager, c[0]);
3993 y = map_bit_to_term(manager, c[1]);
3994
3995 assert(is_boolean_term(manager->terms, x) &&
3996 is_boolean_term(manager->terms, y));
3997
3998 return mk_binary_or(manager, x, y);
3999 }
4000
4001
4002 /*
4003 * Same thing for (xor c[0] c[1])
4004 */
make_xor2(term_manager_t * manager,bit_t * c)4005 static term_t make_xor2(term_manager_t *manager, bit_t *c) {
4006 term_t x, y;
4007
4008 x = map_bit_to_term(manager, c[0]);
4009 y = map_bit_to_term(manager, c[1]);
4010
4011 assert(is_boolean_term(manager->terms, x) &&
4012 is_boolean_term(manager->terms, y));
4013
4014 return mk_binary_xor(manager, x, y);
4015 }
4016
4017
4018
4019 /*
4020 * Recursive function: return the term mapped to node x
4021 * - compute it if needed then store the result in nodes->map[x]
4022 */
map_node_to_term(term_manager_t * manager,node_t x)4023 static term_t map_node_to_term(term_manager_t *manager, node_t x) {
4024 node_table_t *nodes;
4025 term_t t;
4026
4027 nodes = manager->nodes;
4028 assert(nodes != NULL);
4029
4030 t = map_of_node(nodes, x);
4031 if (t < 0) {
4032 assert(t == -1);
4033
4034 switch (node_kind(nodes, x)) {
4035 case CONSTANT_NODE:
4036 // x is true
4037 t = true_term;
4038 break;
4039
4040 case VARIABLE_NODE:
4041 // x is (var t) for a boolean term t
4042 t = var_of_node(nodes, x);
4043 break;
4044
4045 case SELECT_NODE:
4046 // x is (select i u) for a bitvector term u
4047 t = mk_bitextract(manager, var_of_select_node(nodes, x), index_of_select_node(nodes, x));
4048 break;
4049
4050 case OR_NODE:
4051 t = make_or2(manager, children_of_node(nodes, x));
4052 break;
4053
4054 case XOR_NODE:
4055 t = make_xor2(manager, children_of_node(nodes, x));
4056 break;
4057
4058 default:
4059 assert(false);
4060 abort();
4061 break;
4062 }
4063
4064 assert(is_boolean_term(manager->terms, t));
4065 set_map_of_node(nodes, x, t);
4066 }
4067
4068 return t;
4069 }
4070
4071
4072
4073
4074
4075 /*******************
4076 * BVLOGIC TERMS *
4077 ******************/
4078
4079 /*
4080 * Convert buffer b to a bv_constant term
4081 * - side effect: use bv0
4082 */
bvlogic_buffer_get_bvconst(term_manager_t * manager,bvlogic_buffer_t * b)4083 static term_t bvlogic_buffer_get_bvconst(term_manager_t *manager, bvlogic_buffer_t *b) {
4084 bvconstant_t *bv;
4085
4086 assert(bvlogic_buffer_is_constant(b));
4087
4088 bv = &manager->bv0;
4089 bvlogic_buffer_get_constant(b, bv);
4090 return bvconst_term(manager->terms, bv->bitsize, bv->data);
4091 }
4092
4093
4094 /*
4095 * Convert buffer b to a bv-array term
4096 */
bvlogic_buffer_get_bvarray(term_manager_t * manager,bvlogic_buffer_t * b)4097 static term_t bvlogic_buffer_get_bvarray(term_manager_t *manager, bvlogic_buffer_t *b) {
4098 uint32_t i, n;
4099
4100 assert(b->nodes == manager->nodes && manager->nodes != NULL);
4101
4102 // translate each bit of b into a boolean term
4103 // we store the translation in b->bit
4104 n = b->bitsize;
4105 for (i=0; i<n; i++) {
4106 b->bit[i] = map_bit_to_term(manager, b->bit[i]);
4107 }
4108
4109 // build the term (bvarray b->bit[0] ... b->bit[n-1])
4110 return bvarray_term(manager->terms, n, b->bit);
4111 }
4112
4113
4114 /*
4115 * Convert b to a term then reset b.
4116 * - b must not be empty.
4117 * - build a bitvector constant if possible
4118 * - if b is of the form (select 0 t) ... (select k t) and t has bitsize (k+1)
4119 * then return t
4120 * - otherwise build a bitarray term
4121 */
mk_bvlogic_term(term_manager_t * manager,bvlogic_buffer_t * b)4122 term_t mk_bvlogic_term(term_manager_t *manager, bvlogic_buffer_t *b) {
4123 term_t t;
4124 uint32_t n;
4125
4126 n = b->bitsize;
4127 assert(0 < n && n <= YICES_MAX_BVSIZE);
4128
4129 if (bvlogic_buffer_is_constant(b)) {
4130 if (n <= 64) {
4131 // small constant
4132 t = bv64_constant(manager->terms, n, bvlogic_buffer_get_constant64(b));
4133 } else {
4134 // wide constant
4135 t = bvlogic_buffer_get_bvconst(manager, b);
4136 }
4137
4138 } else {
4139 t = bvlogic_buffer_get_var(b);
4140 if (t < 0 || term_bitsize(manager->terms, t) != n) {
4141 // not a variable
4142 t = bvlogic_buffer_get_bvarray(manager, b);
4143 }
4144 }
4145
4146 assert(is_bitvector_term(manager->terms, t) &&
4147 term_bitsize(manager->terms, t) == n);
4148
4149 bvlogic_buffer_clear(b);
4150
4151 return t;
4152 }
4153
4154
4155 #if 1
4156
4157 /*
4158 * Sign extend term t to n bits
4159 * - t must be a bitvector of less than n bits
4160 * - n = number of bits in the result
4161 */
mk_sign_extend_term(term_manager_t * manager,term_t t,uint32_t n)4162 static term_t mk_sign_extend_term(term_manager_t *manager, term_t t, uint32_t n) {
4163 bvlogic_buffer_t *b;
4164
4165 assert(is_bitvector_term(manager->terms, t) &&
4166 term_bitsize(manager->terms, t) < n);
4167
4168 b = term_manager_get_bvlogic_buffer(manager);
4169 bvlogic_buffer_set_term(b, manager->terms, t);
4170 bvlogic_buffer_sign_extend(b, n);
4171
4172 return mk_bvlogic_term(manager, b);
4173 }
4174
4175 #endif
4176
4177
4178 /***************************
4179 * BITVECTOR POLYNOMIALS *
4180 **************************/
4181
4182 /*
4183 * Store array [false_term, ..., false_term] into vector v
4184 */
bvarray_set_zero_bv(ivector_t * v,uint32_t n)4185 static void bvarray_set_zero_bv(ivector_t *v, uint32_t n) {
4186 uint32_t i;
4187
4188 assert(0 < n && n <= YICES_MAX_BVSIZE);
4189 resize_ivector(v, n);
4190 for (i=0; i<n; i++) {
4191 v->data[i] = false_term;
4192 }
4193 }
4194
4195 /*
4196 * Store constant c into vector v
4197 * - n = number of bits in c
4198 */
bvarray_copy_constant(ivector_t * v,uint32_t n,uint32_t * c)4199 static void bvarray_copy_constant(ivector_t *v, uint32_t n, uint32_t *c) {
4200 uint32_t i;
4201
4202 assert(0 < n && n <= YICES_MAX_BVSIZE);
4203 resize_ivector(v, n);
4204 for (i=0; i<n; i++) {
4205 v->data[i] = bool2term(bvconst_tst_bit(c, i));
4206 }
4207 }
4208
4209 /*
4210 * Same thing for a small constant c
4211 */
bvarray_copy_constant64(ivector_t * v,uint32_t n,uint64_t c)4212 static void bvarray_copy_constant64(ivector_t *v, uint32_t n, uint64_t c) {
4213 uint32_t i;
4214
4215 assert(0 < n && n <= 64);
4216 resize_ivector(v, n);
4217 for (i=0; i<n; i++) {
4218 v->data[i] = bool2term(tst_bit64(c, i));
4219 }
4220 }
4221
4222
4223 /*
4224 * Check whether v + c * a can be converted to (v | (a << k)) for some k
4225 * - return true if that can be done and update v to (v | (a << k))
4226 * - otherwise, return false and keep v unchanged
4227 * - a must be an array of n boolean terms
4228 * - v must also contain n boolean terms
4229 */
bvarray_check_addmul(ivector_t * v,uint32_t n,uint32_t * c,term_t * a)4230 static bool bvarray_check_addmul(ivector_t *v, uint32_t n, uint32_t *c, term_t *a) {
4231 uint32_t i, w;
4232 int32_t k;
4233
4234 w = (n + 31) >> 5; // number of words in c
4235 if (bvconst_is_zero(c, w)) {
4236 return true;
4237 }
4238
4239 k = bvconst_is_power_of_two(c, w);
4240 if (k < 0) {
4241 return false;
4242 }
4243
4244 // c is 2^k so (c * a) is equal to (a << k)
4245 // check whether we can convert the addition into a bitwise or,
4246 // that is, check whether (v + (a << k)) is equal to (v | (a << k))
4247 assert(0 <= k && k < n);
4248 for (i=k; i<n; i++) {
4249 if (v->data[i] != false_term && a[i-k] != false_term) {
4250 return false;
4251 }
4252 }
4253
4254 // update v here
4255 for (i=k; i<n; i++) {
4256 if (a[i-k] != false_term) {
4257 assert(v->data[i] == false_term);
4258 v->data[i] = a[i-k];
4259 }
4260 }
4261
4262 return true;
4263 }
4264
4265
4266 /*
4267 * Same thing for c stored as a small constant (64 bits at most)
4268 */
bvarray_check_addmul64(ivector_t * v,uint32_t n,uint64_t c,term_t * a)4269 static bool bvarray_check_addmul64(ivector_t *v, uint32_t n, uint64_t c, term_t *a) {
4270 uint32_t i, k;
4271
4272 assert(0 < n && n <= 64 && c == norm64(c, n));
4273
4274 if (c == 0) {
4275 return true;
4276 }
4277
4278 k = ctz64(c); // k = index of the rightmost 1 in c
4279 assert(0 <= k && k <= 63);
4280 if (c != (((uint64_t) 1) << k)) {
4281 // c != 2^k
4282 return false;
4283 }
4284
4285 // c is 2^k check whether v + (a << k) is equal to v | (a << k)
4286 assert(0 <= k && k < n);
4287 for (i=k; i<n; i++) {
4288 if (v->data[i] != false_term && a[i-k] != false_term) {
4289 return false;
4290 }
4291 }
4292
4293 // update v here
4294 for (i=k; i<n; i++) {
4295 if (a[i-k] != false_term) {
4296 assert(v->data[i] == false_term);
4297 v->data[i] = a[i-k];
4298 }
4299 }
4300
4301 return true;
4302 }
4303
4304
4305
4306
4307 /*
4308 * Check whether power product r is equal to a bit-array term t
4309 * - if so return t's descriptor, otherwise return NULL
4310 */
pprod_get_bvarray(term_table_t * tbl,pprod_t * r)4311 static composite_term_t *pprod_get_bvarray(term_table_t *tbl, pprod_t *r) {
4312 composite_term_t *bv;
4313 term_t t;
4314
4315 bv = NULL;
4316 if (pp_is_var(r)) {
4317 t = var_of_pp(r);
4318 if (term_kind(tbl, t) == BV_ARRAY) {
4319 bv = composite_for_idx(tbl, index_of(t));
4320 }
4321 }
4322
4323 return bv;
4324 }
4325
4326
4327 /*
4328 * Attempt to convert a bvarith buffer to a bv-array term
4329 * - b = bvarith buffer (list of monomials)
4330 * - return NULL_TERM if the conversion fails
4331 * - return a term t if the conversion succeeds.
4332 * - side effect: use vector0
4333 */
convert_bvarith_to_bvarray(term_manager_t * manager,bvarith_buffer_t * b)4334 static term_t convert_bvarith_to_bvarray(term_manager_t *manager, bvarith_buffer_t *b) {
4335 composite_term_t *bv;
4336 bvmlist_t *m;
4337 ivector_t *v;
4338 uint32_t n;
4339
4340 v = &manager->vector0;
4341
4342 n = b->bitsize;
4343 m = b->list; // first monomial
4344 if (m->prod == empty_pp) {
4345 // copy constant into v
4346 bvarray_copy_constant(v, n, m->coeff);
4347 m = m->next;
4348 } else {
4349 // initialize v to 0b0000..0
4350 bvarray_set_zero_bv(v, n);
4351 }
4352
4353 while (m->next != NULL) {
4354 bv = pprod_get_bvarray(manager->terms, m->prod);
4355 if (bv == NULL) return NULL_TERM;
4356
4357 assert(bv->arity == n);
4358
4359 // try to convert coeff * bv into shift + bitwise or
4360 if (! bvarray_check_addmul(v, n, m->coeff, bv->arg)) {
4361 return NULL_TERM; // conversion failed
4362 }
4363 m = m->next;
4364 }
4365
4366 // Success: construct a bit array from v
4367 return bvarray_term(manager->terms, n, v->data);
4368 }
4369
4370
4371 /*
4372 * Attempt to convert a bvarith64 buffer to a bv-array term
4373 * - b = bvarith buffer (list of monomials)
4374 * - return NULL_TERM if the conversion fails
4375 * - return a term t if the conversion succeeds.
4376 * - side effect: use vector0
4377 */
convert_bvarith64_to_bvarray(term_manager_t * manager,bvarith64_buffer_t * b)4378 static term_t convert_bvarith64_to_bvarray(term_manager_t *manager, bvarith64_buffer_t *b) {
4379 composite_term_t *bv;
4380 bvmlist64_t *m;
4381 ivector_t *v;
4382 uint32_t n;
4383
4384 v = &manager->vector0;
4385
4386 n = b->bitsize;
4387 m = b->list; // first monomial
4388 if (m->prod == empty_pp) {
4389 // copy constant into vector0
4390 bvarray_copy_constant64(v, n, m->coeff);
4391 m = m->next;
4392 } else {
4393 // initialize vector0 to 0
4394 bvarray_set_zero_bv(v, n);
4395 }
4396
4397 while (m->next != NULL) {
4398 bv = pprod_get_bvarray(manager->terms, m->prod);
4399 if (bv == NULL) return NULL_TERM;
4400
4401 assert(bv->arity == n);
4402
4403 // try to convert coeff * bv into shift + bitwise or
4404 if (! bvarray_check_addmul64(v, n, m->coeff, bv->arg)) {
4405 return NULL_TERM; // conversion failed
4406 }
4407 m = m->next;
4408 }
4409
4410 // Success: construct a bit array from v
4411 return bvarray_term(manager->terms, n, v->data);
4412 }
4413
4414
4415 /*
4416 * Constant bitvector with all bits 0
4417 * - n = bitsize (must satisfy 0 < n && n <= YICES_MAX_BVSIZE)
4418 * - side effect: modify bv0
4419 */
make_zero_bv(term_manager_t * manager,uint32_t n)4420 static term_t make_zero_bv(term_manager_t *manager, uint32_t n) {
4421 bvconstant_t *bv;
4422
4423 assert(0 < n && n <= YICES_MAX_BVSIZE);
4424
4425 bv = &manager->bv0;
4426
4427 if (n > 64) {
4428 bvconstant_set_all_zero(bv, n);
4429 return bvconst_term(manager->terms, bv->bitsize, bv->data);
4430 } else {
4431 return bv64_constant(manager->terms, n, 0);
4432 }
4433 }
4434
4435
4436 /*
4437 * Convert a polynomial buffer to a bitvector terms:
4438 * - b must use the same pprod as manager (i.e., b->ptbl = manager->pprods)
4439 * - b may be equal to manager->bvarith_buffer
4440 * - side effect: b is reset
4441 *
4442 * This normalizes b first then check for the following:
4443 * 1) b reduced to a single variable x: return x
4444 * 2) b reduced to a power product pp: return pp
4445 * 3) b is constant, return a BV64_CONSTANT or BV_CONSTANT term
4446 * 4) b can be converted to a BV_ARRAY term (by converting + and *
4447 * to bitwise or and shift): return the BV_ARRAY
4448 *
4449 * Otherwise, build a bit-vector polynomial.
4450 */
mk_bvarith_term(term_manager_t * manager,bvarith_buffer_t * b)4451 term_t mk_bvarith_term(term_manager_t *manager, bvarith_buffer_t *b) {
4452 bvmlist_t *m;
4453 pprod_t *r;
4454 uint32_t n, p, k;
4455 term_t t;
4456
4457 assert(b->bitsize > 0);
4458
4459 bvarith_buffer_normalize(b);
4460
4461 n = b->bitsize;
4462 k = (n + 31) >> 5;
4463 p = b->nterms;
4464 if (p == 0) {
4465 // zero
4466 t = make_zero_bv(manager, n);
4467 goto done;
4468 }
4469
4470 if (p == 1) {
4471 m = b->list; // unique monomial of b
4472 r = m->prod;
4473 if (r == empty_pp) {
4474 // constant
4475 t = bvconst_term(manager->terms, n, m->coeff);
4476 goto done;
4477 }
4478 if (bvconst_is_one(m->coeff, k)) {
4479 // power product
4480 t = pp_is_var(r) ? var_of_pp(r) : pprod_term(manager->terms, r);
4481 goto done;
4482 }
4483 }
4484
4485 // try to convert to a bvarray term
4486 t = convert_bvarith_to_bvarray(manager, b);
4487 if (t == NULL_TERM) {
4488 // conversion failed: build a bvpoly
4489 t = bv_poly(manager->terms, b);
4490 }
4491
4492 done:
4493 reset_bvarith_buffer(b);
4494 assert(is_bitvector_term(manager->terms, t) &&
4495 term_bitsize(manager->terms, t) == n);
4496
4497 return t;
4498 }
4499
4500
4501 #if 0
4502 /*
4503 * PROVISIONAL FOR TESTING
4504 */
4505 #include <inttypes.h>
4506 #include <stdio.h>
4507
4508 static void test_width(term_manager_t *manager, term_t t) {
4509 bv64_abs_t abs;
4510 uint32_t n;
4511
4512 bv64_abstract_term(manager->terms, t, &abs);
4513 n = term_bitsize(manager->terms, t);
4514 if (bv64_abs_nontrivial(&abs, n)) {
4515 printf("---> non-trivial abstraction for term t%"PRId32" (%"PRIu32" bits)\n", t, n);
4516 printf(" [%"PRId64", %"PRId64"] (%"PRIu32" bits)\n", abs.low, abs.high, abs.nbits);
4517 fflush(stdout);
4518 }
4519 }
4520 #endif
4521
4522
4523 /*
4524 * Truncate term t to n bits
4525 */
truncate_bv_term(term_manager_t * manager,uint32_t n,term_t t)4526 static term_t truncate_bv_term(term_manager_t *manager, uint32_t n, term_t t) {
4527 bvlogic_buffer_t *b;
4528
4529 assert(is_bitvector_term(manager->terms, t) && term_bitsize(manager->terms, t) >= n && n>0);
4530
4531 b = term_manager_get_bvlogic_buffer(manager);
4532 bvlogic_buffer_set_slice_term(b, manager->terms, 0, n-1, t);
4533
4534 return mk_bvlogic_term(manager, b);
4535 }
4536
4537 /*
4538 * Truncate p to n bits
4539 */
truncate_pprod(term_manager_t * manager,uint32_t n,pprod_t * p)4540 static pprod_t *truncate_pprod(term_manager_t *manager, uint32_t n, pprod_t *p) {
4541 pp_buffer_t *buffer;
4542 pprod_t *r;
4543 uint32_t i, k;
4544 term_t t;
4545
4546 k = p->len;
4547
4548 buffer = term_manager_get_pp_buffer(manager);
4549 assert(buffer->len == 0);
4550 for (i=0; i<k; i++) {
4551 t = truncate_bv_term(manager, n, p->prod[i].var);
4552 pp_buffer_mul_varexp(buffer, t, p->prod[i].exp);
4553 }
4554 pp_buffer_normalize(buffer);
4555 r = pprod_from_buffer(manager->pprods, buffer);
4556 pp_buffer_reset(buffer);
4557
4558 return r;
4559 }
4560
4561 /*
4562 * Construct a power-product term:
4563 * - n = number of bits (must be between 1 and 64)
4564 * - p = power product
4565 */
mk_pprod64_term(term_manager_t * manager,uint32_t n,pprod_t * p)4566 static term_t mk_pprod64_term(term_manager_t *manager, uint32_t n, pprod_t *p) {
4567 bv64_abs_t abs;
4568 pprod_t *r;
4569 term_t t;
4570
4571 assert(1 <= n && n <= 64);
4572 bv64_abs_pprod(manager->terms, p, n, &abs);
4573
4574 #if 0
4575 if (bv64_abs_nontrivial(&abs, n)) {
4576 printf("---> reducible power product: %"PRIu32" bits\n", n);
4577 printf(" [%"PRId64", %"PRId64"] (%"PRIu32" bits)\n", abs.low, abs.high, abs.nbits);
4578 fflush(stdout);
4579 }
4580 #endif
4581
4582 if (abs.nbits < n) {
4583 r = truncate_pprod(manager, abs.nbits, p);
4584 t = pprod_term(manager->terms, r);
4585 t = mk_sign_extend_term(manager, t, n);
4586 } else {
4587 t = pprod_term(manager->terms, p);
4588 }
4589
4590 return t;
4591 }
4592
4593 #if 0
4594 // THIS MAKES THINGS WORSE
4595
4596 /*
4597 * Truncate a polynomial to n bits
4598 * - b = buffer that stores the polynomial
4599 * - b must be normalized
4600 * - return a term
4601 */
4602 static term_t truncate_bvarith64_buffer(term_manager_t *manager, bvarith64_buffer_t *b, uint32_t n) {
4603 bvarith64_buffer_t *aux;
4604 bvmlist64_t *q;
4605 pprod_t *r;
4606 uint64_t c;
4607 uint32_t i, m;
4608 term_t t;
4609
4610 assert(1 <= n && n <= 64);
4611
4612 aux = term_manager_get_bvarith64_aux_buffer(manager);
4613 bvarith64_buffer_prepare(aux, n);
4614
4615 m = b->nterms;
4616 q = b->list;
4617 assert(m >= 1);
4618 for (i=0; i<m; i++) {
4619 r = q->prod;
4620 c = norm64(q->coeff, n); // coeff truncated to n bits
4621 if (r == empty_pp) {
4622 bvarith64_buffer_add_const(aux, c);
4623 } else if (pp_is_var(r)) {
4624 t = truncate_bv_term(manager, n, var_of_pp(r));
4625 bvarith64_buffer_add_varmono(aux, c, t);
4626 } else {
4627 r = truncate_pprod(manager, n, r);
4628 bvarith64_buffer_add_mono(aux, c, r);
4629 }
4630 q = q->next;
4631 }
4632
4633 bvarith64_buffer_normalize(aux);
4634 t = bv64_poly(manager->terms, aux);
4635 reset_bvarith64_buffer(aux);
4636
4637 return t;
4638 }
4639
4640
4641 /*
4642 * Check whether we can reduce b's width.
4643 * - if so return the (sign extend (reduced width term) ...)
4644 * - otherwise return NULL_TERM
4645 */
4646 static term_t try_bvarith64_truncation(term_manager_t *manager, bvarith64_buffer_t *b) {
4647 bv64_abs_t abs;
4648 uint32_t n;
4649 term_t t;
4650
4651 n = b->bitsize;
4652 assert(1 <= n && n <= 64);
4653 bv64_abs_buffer(manager->terms, b, n, &abs);
4654
4655 #if 0
4656 if (bv64_abs_nontrivial(&abs, n)) {
4657 printf("---> reducible polynomial: %"PRIu32" bits\n", n);
4658 printf(" [%"PRId64", %"PRId64"] (%"PRIu32" bits)\n", abs.low, abs.high, abs.nbits);
4659 fflush(stdout);
4660 }
4661 #endif
4662
4663 t = NULL_TERM;
4664 if (abs.nbits < n) {
4665 t = truncate_bvarith64_buffer(manager, b, abs.nbits);
4666 t = mk_sign_extend_term(manager, t, n);
4667 }
4668
4669 return t;
4670 }
4671 #endif
4672
4673 /*
4674 * Normalize b then convert it to a term and reset b
4675 */
mk_bvarith64_term(term_manager_t * manager,bvarith64_buffer_t * b)4676 term_t mk_bvarith64_term(term_manager_t *manager, bvarith64_buffer_t *b) {
4677 bvmlist64_t *m;
4678 pprod_t *r;
4679 uint32_t n, p;
4680 term_t t;
4681
4682 assert(b->bitsize > 0);
4683
4684 bvarith64_buffer_normalize(b);
4685
4686 n = b->bitsize;
4687 p = b->nterms;
4688 if (p == 0) {
4689 // zero
4690 t = make_zero_bv(manager, n);
4691 goto done;
4692 }
4693
4694 if (p == 1) {
4695 m = b->list; // unique monomial of b
4696 r = m->prod;
4697 if (r == empty_pp) {
4698 // constant
4699 t = bv64_constant(manager->terms, n, m->coeff);
4700 goto done;
4701 }
4702 if (m->coeff == 1) {
4703 // power product
4704 // t = pp_is_var(r) ? var_of_pp(r) : pprod_term(manager->terms, r);
4705 t = pp_is_var(r) ? var_of_pp(r) : mk_pprod64_term(manager, n, r);
4706 goto done;
4707 }
4708 }
4709
4710 // try to convert to a bvarray term
4711 t = convert_bvarith64_to_bvarray(manager, b);
4712 if (t != NULL_TERM) goto done;
4713
4714 #if 0
4715 // THIS MAKES THINGS WORSE
4716 // try width reduction
4717 t = try_bvarith64_truncation(manager, b);
4718 if (t != NULL_TERM) goto done;
4719 #endif
4720
4721 // default
4722 t = bv64_poly(manager->terms, b);
4723
4724
4725 done:
4726 reset_bvarith64_buffer(b);
4727 assert(is_bitvector_term(manager->terms, t) &&
4728 term_bitsize(manager->terms, t) == n);
4729
4730 return t;
4731 }
4732
4733
4734
4735 /***************
4736 * BIT ARRAY *
4737 **************/
4738
4739 /*
4740 * Bit array
4741 * - a must be an array of n boolean terms
4742 * - n must be positive and no more than YICES_MAX_BVSIZE
4743 */
mk_bvarray(term_manager_t * manager,uint32_t n,const term_t * a)4744 term_t mk_bvarray(term_manager_t *manager, uint32_t n, const term_t *a) {
4745 bvlogic_buffer_t *b;
4746
4747 assert(0 < n && n <= YICES_MAX_BVSIZE);
4748
4749 b = term_manager_get_bvlogic_buffer(manager);
4750 bvlogic_buffer_set_term_array(b, manager->terms, n, a);
4751 return mk_bvlogic_term(manager, b);
4752 }
4753
4754
4755 /**********************
4756 * BITVECTOR SHIFT *
4757 *********************/
4758
4759 /*
4760 * All shift operators takes two bit-vector arguments of the same size.
4761 * The first argument is shifted. The second argument is the shift amount.
4762 * - bvshl t1 t2: shift left, padding with 0
4763 * - bvlshr t1 t2: logical shift right (padding with 0)
4764 * - bvashr t1 t2: arithmetic shift right (copy the sign bit)
4765 *
4766 * We check whether t2 is a bit-vector constant and convert to
4767 * constant bit-shifts in such cases.
4768 */
4769
4770
4771 /*
4772 * SHIFT LEFT
4773 */
4774
4775 // shift amount given by a small bitvector constant
mk_bvshl_const64(term_manager_t * manager,term_t t1,bvconst64_term_t * c)4776 static term_t mk_bvshl_const64(term_manager_t *manager, term_t t1, bvconst64_term_t *c) {
4777 bvlogic_buffer_t *b;
4778
4779 b = term_manager_get_bvlogic_buffer(manager);
4780 bvlogic_buffer_set_term(b, manager->terms, t1);
4781 bvlogic_buffer_shl_constant64(b, c->bitsize, c->value);
4782
4783 return mk_bvlogic_term(manager, b);
4784 }
4785
4786 // shift amount given by a large bitvector constant
mk_bvshl_const(term_manager_t * manager,term_t t1,bvconst_term_t * c)4787 static term_t mk_bvshl_const(term_manager_t *manager, term_t t1, bvconst_term_t *c) {
4788 bvlogic_buffer_t *b;
4789
4790 b = term_manager_get_bvlogic_buffer(manager);
4791 bvlogic_buffer_set_term(b, manager->terms, t1);
4792 bvlogic_buffer_shl_constant(b, c->bitsize, c->data);
4793
4794 return mk_bvlogic_term(manager, b);
4795 }
4796
4797 // special case: if t1 is 0b000...0 then (bvshl t1 t2) = t2 for any t2
term_is_bvzero(term_table_t * tbl,term_t t1)4798 static bool term_is_bvzero(term_table_t *tbl, term_t t1) {
4799 bvconst64_term_t *u;
4800 bvconst_term_t *v;
4801 uint32_t k;
4802
4803 switch (term_kind(tbl, t1)) {
4804 case BV64_CONSTANT:
4805 u = bvconst64_term_desc(tbl, t1);
4806 assert(u->value == norm64(u->value, u->bitsize));
4807 return u->value == 0;
4808
4809 case BV_CONSTANT:
4810 v = bvconst_term_desc(tbl, t1);
4811 k = (v->bitsize + 31) >> 5; // number of words in v
4812 return bvconst_is_zero(v->data, k);
4813
4814 default:
4815 return false;
4816 }
4817 }
4818
4819
mk_bvshl(term_manager_t * manager,term_t t1,term_t t2)4820 term_t mk_bvshl(term_manager_t *manager, term_t t1, term_t t2) {
4821 term_table_t *tbl;
4822
4823 tbl = manager->terms;
4824
4825 assert(is_bitvector_term(tbl, t1) && is_bitvector_term(tbl, t2)
4826 && term_type(tbl, t1) == term_type(tbl, t2));
4827
4828 switch (term_kind(tbl, t2)) {
4829 case BV64_CONSTANT:
4830 return mk_bvshl_const64(manager, t1, bvconst64_term_desc(tbl, t2));
4831
4832 case BV_CONSTANT:
4833 return mk_bvshl_const(manager, t1, bvconst_term_desc(tbl, t2));
4834
4835 default:
4836 if (term_is_bvzero(tbl, t1)) {
4837 return t1;
4838 } else {
4839 return bvshl_term(tbl, t1, t2);
4840 }
4841 }
4842 }
4843
4844
4845
4846 /*
4847 * LOGICAL SHIFT RIGHT
4848 */
4849
4850 // shift amount given by a small bitvector constant
mk_bvlshr_const64(term_manager_t * manager,term_t t1,bvconst64_term_t * c)4851 static term_t mk_bvlshr_const64(term_manager_t *manager, term_t t1, bvconst64_term_t *c) {
4852 bvlogic_buffer_t *b;
4853
4854 b = term_manager_get_bvlogic_buffer(manager);
4855 bvlogic_buffer_set_term(b, manager->terms, t1);
4856 bvlogic_buffer_lshr_constant64(b, c->bitsize, c->value);
4857
4858 return mk_bvlogic_term(manager, b);
4859 }
4860
4861 // logical shift right: amount given by a large bitvector constant
mk_bvlshr_const(term_manager_t * manager,term_t t1,bvconst_term_t * c)4862 static term_t mk_bvlshr_const(term_manager_t *manager, term_t t1, bvconst_term_t *c) {
4863 bvlogic_buffer_t *b;
4864
4865 b = term_manager_get_bvlogic_buffer(manager);
4866 bvlogic_buffer_set_term(b, manager->terms, t1);
4867 bvlogic_buffer_lshr_constant(b, c->bitsize, c->data);
4868
4869 return mk_bvlogic_term(manager, b);
4870 }
4871
4872
mk_bvlshr(term_manager_t * manager,term_t t1,term_t t2)4873 term_t mk_bvlshr(term_manager_t *manager, term_t t1, term_t t2) {
4874 term_table_t *tbl;
4875
4876 tbl = manager->terms;
4877
4878 assert(is_bitvector_term(tbl, t1) && is_bitvector_term(tbl, t2)
4879 && term_type(tbl, t1) == term_type(tbl, t2));
4880
4881 // rewrite: (bvlshr x x) --> 0b000000 ... 0
4882 if (t1 == t2) return make_zero_bv(manager, term_bitsize(tbl, t1));
4883
4884 switch (term_kind(tbl, t2)) {
4885 case BV64_CONSTANT:
4886 return mk_bvlshr_const64(manager, t1, bvconst64_term_desc(tbl, t2));
4887
4888 case BV_CONSTANT:
4889 return mk_bvlshr_const(manager, t1, bvconst_term_desc(tbl, t2));
4890
4891 default:
4892 // as above: if t1 is zero, then shifting does not change it
4893 if (term_is_bvzero(tbl, t1)) {
4894 return t1;
4895 } else {
4896 return bvlshr_term(tbl, t1, t2);
4897 }
4898 }
4899 }
4900
4901
4902 /*
4903 * ARITHMETIC SHIFT RIGHT
4904 */
4905
4906 // shift amount given by a small bitvector constant
mk_bvashr_const64(term_manager_t * manager,term_t t1,bvconst64_term_t * c)4907 static term_t mk_bvashr_const64(term_manager_t *manager, term_t t1, bvconst64_term_t *c) {
4908 bvlogic_buffer_t *b;
4909
4910 b = term_manager_get_bvlogic_buffer(manager);
4911 bvlogic_buffer_set_term(b, manager->terms, t1);
4912 bvlogic_buffer_ashr_constant64(b, c->bitsize, c->value);
4913
4914 return mk_bvlogic_term(manager, b);
4915 }
4916
4917 // shift amount given by a large bitvector constant
mk_bvashr_const(term_manager_t * manager,term_t t1,bvconst_term_t * c)4918 static term_t mk_bvashr_const(term_manager_t *manager, term_t t1, bvconst_term_t *c) {
4919 bvlogic_buffer_t *b;
4920
4921 b = term_manager_get_bvlogic_buffer(manager);
4922 bvlogic_buffer_set_term(b, manager->terms, t1);
4923 bvlogic_buffer_ashr_constant(b, c->bitsize, c->data);
4924
4925 return mk_bvlogic_term(manager, b);
4926 }
4927
4928 // special case: if t1 is 0b00...00 or 0b11...11 then arithmetic shift
4929 // leaves t1 unchanged (whatever t2)
term_is_bvashr_invariant(term_table_t * tbl,term_t t1)4930 static bool term_is_bvashr_invariant(term_table_t *tbl, term_t t1) {
4931 bvconst64_term_t *u;
4932 bvconst_term_t *v;
4933 uint32_t k;
4934
4935 switch (term_kind(tbl, t1)) {
4936 case BV64_CONSTANT:
4937 u = bvconst64_term_desc(tbl, t1);
4938 assert(u->value == norm64(u->value, u->bitsize));
4939 return u->value == 0 || bvconst64_is_minus_one(u->value, u->bitsize);
4940
4941 case BV_CONSTANT:
4942 v = bvconst_term_desc(tbl, t1);
4943 k = (v->bitsize + 31) >> 5; // number of words in v
4944 return bvconst_is_zero(v->data, k) || bvconst_is_minus_one(v->data, v->bitsize);
4945
4946 default:
4947 return false;
4948 }
4949
4950 }
4951
mk_bvashr(term_manager_t * manager,term_t t1,term_t t2)4952 term_t mk_bvashr(term_manager_t *manager, term_t t1, term_t t2) {
4953 term_table_t *tbl;
4954
4955 tbl = manager->terms;
4956
4957 assert(is_bitvector_term(tbl, t1) && is_bitvector_term(tbl, t2)
4958 && term_type(tbl, t1) == term_type(tbl, t2));
4959
4960 // possible rewrite:
4961 // (bvashr x x) = if x<0 then 0b11111.. else 0b000...
4962
4963 switch (term_kind(tbl, t2)) {
4964 case BV64_CONSTANT:
4965 return mk_bvashr_const64(manager, t1, bvconst64_term_desc(tbl, t2));
4966
4967 case BV_CONSTANT:
4968 return mk_bvashr_const(manager, t1, bvconst_term_desc(tbl, t2));
4969
4970 default:
4971 if (term_is_bvashr_invariant(tbl, t1)) {
4972 return t1;
4973 } else {
4974 return bvashr_term(tbl, t1, t2);
4975 }
4976 }
4977 }
4978
4979
4980
4981 /************************
4982 * BITVECTOR DIVISION *
4983 ***********************/
4984
4985 /*
4986 * All division/remainder constructors are binary operators with two
4987 * bitvector arguments of the same size.
4988 * - bvdiv: quotient in unsigned division
4989 * - bvrem: remainder in unsigned division
4990 * - bvsdiv: quotient in signed division (rounding toward 0)
4991 * - bvsrem: remainder in signed division
4992 * - bvsmod: remainder in floor division (signed division, rounding toward -infinity)
4993 *
4994 * We simplify if the two arguments are constants.
4995 *
4996 * TODO: We could convert division/remainder when t2 is a constant powers of two
4997 * to shift and bit masking operations?
4998 */
4999
5000
5001 /*
5002 * Check whether b is a power of 2.
5003 * - if so return the k such such b = 2^k
5004 * - otherwise, return -1
5005 */
bvconst64_term_is_power_of_two(bvconst64_term_t * b)5006 static int32_t bvconst64_term_is_power_of_two(bvconst64_term_t *b) {
5007 uint32_t k;
5008
5009 if (b->value != 0) {
5010 k = ctz64(b->value);
5011 assert(0 <= k && k < b->bitsize && b->bitsize <= 64);
5012 if (b->value == ((uint64_t) 1) << k) {
5013 return k;
5014 }
5015 }
5016 return -1;
5017 }
5018
bvconst_term_is_power_of_two(bvconst_term_t * b)5019 static int32_t bvconst_term_is_power_of_two(bvconst_term_t *b) {
5020 uint32_t w;
5021
5022 w = (b->bitsize + 31) >> 5; // number of words in b->data
5023 return bvconst_is_power_of_two(b->data, w);
5024 }
5025
5026
5027 /*
5028 * UNSIGNED DIVISION: QUOTIENT
5029 */
bvdiv_const64(term_manager_t * manager,bvconst64_term_t * a,bvconst64_term_t * b)5030 static term_t bvdiv_const64(term_manager_t *manager, bvconst64_term_t *a, bvconst64_term_t *b) {
5031 uint64_t x;
5032 uint32_t n;
5033
5034 n = a->bitsize;
5035 assert(n == b->bitsize);
5036 x = bvconst64_udiv2z(a->value, b->value, n);
5037 assert(x == norm64(x, n));
5038
5039 return bv64_constant(manager->terms, n, x);
5040 }
5041
5042
bvdiv_const(term_manager_t * manager,bvconst_term_t * a,bvconst_term_t * b)5043 static term_t bvdiv_const(term_manager_t *manager, bvconst_term_t *a, bvconst_term_t *b) {
5044 bvconstant_t *bv;
5045 uint32_t n;
5046
5047 n = a->bitsize;
5048 assert(n == b->bitsize && n > 64);
5049
5050 bv = &manager->bv0;
5051
5052 bvconstant_set_bitsize(bv, n);
5053 bvconst_udiv2z(bv->data, n, a->data, b->data);
5054 bvconst_normalize(bv->data, n);
5055
5056 return bvconst_term(manager->terms, n, bv->data);
5057 }
5058
5059
5060 // divide t1 by 2^k
bvdiv_power(term_manager_t * manager,term_t t1,uint32_t k)5061 static term_t bvdiv_power(term_manager_t *manager, term_t t1, uint32_t k) {
5062 bvlogic_buffer_t *b;
5063
5064 if (k == 0) return t1;
5065
5066 b = term_manager_get_bvlogic_buffer(manager);
5067 bvlogic_buffer_set_term(b, manager->terms, t1);
5068 bvlogic_buffer_shift_right0(b, k);
5069
5070 return mk_bvlogic_term(manager, b);
5071 }
5072
5073
mk_bvdiv(term_manager_t * manager,term_t t1,term_t t2)5074 term_t mk_bvdiv(term_manager_t *manager, term_t t1, term_t t2) {
5075 term_table_t *tbl;
5076 int32_t k;
5077
5078 tbl = manager->terms;
5079
5080 assert(is_bitvector_term(tbl, t1) && is_bitvector_term(tbl, t2)
5081 && term_type(tbl, t1) == term_type(tbl, t2));
5082
5083 switch (term_kind(tbl, t2)) {
5084 case BV64_CONSTANT:
5085 if (term_kind(tbl, t1) == BV64_CONSTANT) {
5086 return bvdiv_const64(manager, bvconst64_term_desc(tbl, t1), bvconst64_term_desc(tbl, t2));
5087 }
5088 k = bvconst64_term_is_power_of_two(bvconst64_term_desc(tbl, t2));
5089 if (k >= 0) {
5090 return bvdiv_power(manager, t1, k);
5091 }
5092 break;
5093
5094 case BV_CONSTANT:
5095 if (term_kind(tbl, t1) == BV_CONSTANT) {
5096 return bvdiv_const(manager, bvconst_term_desc(tbl, t1), bvconst_term_desc(tbl, t2));
5097 }
5098 k = bvconst_term_is_power_of_two(bvconst_term_desc(tbl, t2));
5099 if (k >= 0) {
5100 return bvdiv_power(manager, t1, k);
5101 }
5102 break;
5103
5104 default:
5105 break;
5106 }
5107
5108 return bvdiv_term(tbl, t1, t2);
5109 }
5110
5111
5112 /*
5113 * UNSIGNED DIVISION: REMAINDER
5114 */
bvrem_const64(term_manager_t * manager,bvconst64_term_t * a,bvconst64_term_t * b)5115 static term_t bvrem_const64(term_manager_t *manager, bvconst64_term_t *a, bvconst64_term_t *b) {
5116 uint64_t x;
5117 uint32_t n;
5118
5119 n = a->bitsize;
5120 assert(n == b->bitsize);
5121 x = bvconst64_urem2z(a->value, b->value, n);
5122 assert(x == norm64(x, n));
5123
5124 return bv64_constant(manager->terms, n, x);
5125 }
5126
bvrem_const(term_manager_t * manager,bvconst_term_t * a,bvconst_term_t * b)5127 static term_t bvrem_const(term_manager_t *manager, bvconst_term_t *a, bvconst_term_t *b) {
5128 bvconstant_t *bv;
5129 uint32_t n;
5130
5131 n = a->bitsize;
5132 assert(n == b->bitsize && n > 64);
5133
5134 bv = &manager->bv0;
5135
5136 bvconstant_set_bitsize(bv, n);
5137 bvconst_urem2z(bv->data, n, a->data, b->data);
5138 bvconst_normalize(bv->data, n);
5139
5140 return bvconst_term(manager->terms, n, bv->data);
5141 }
5142
5143 // remainder of t1/2^k
bvrem_power(term_manager_t * manager,term_t t1,uint32_t k)5144 static term_t bvrem_power(term_manager_t *manager, term_t t1, uint32_t k) {
5145 bvlogic_buffer_t *b;
5146 uint32_t n;
5147
5148 n = term_bitsize(manager->terms, t1);
5149 assert(0 <= k && k < n);
5150
5151 b = term_manager_get_bvlogic_buffer(manager);
5152 bvlogic_buffer_set_low_mask(b, k, n);
5153 bvlogic_buffer_and_term(b, manager->terms, t1);
5154
5155 return mk_bvlogic_term(manager, b);
5156 }
5157
5158
mk_bvrem(term_manager_t * manager,term_t t1,term_t t2)5159 term_t mk_bvrem(term_manager_t *manager, term_t t1, term_t t2) {
5160 term_table_t *tbl;
5161 int32_t k;
5162
5163 tbl = manager->terms;
5164
5165 assert(is_bitvector_term(tbl, t1) && is_bitvector_term(tbl, t2)
5166 && term_type(tbl, t1) == term_type(tbl, t2));
5167
5168 switch (term_kind(tbl, t2)) {
5169 case BV64_CONSTANT:
5170 if (term_kind(tbl, t1) == BV64_CONSTANT) {
5171 return bvrem_const64(manager, bvconst64_term_desc(tbl, t1), bvconst64_term_desc(tbl, t2));
5172 }
5173 k = bvconst64_term_is_power_of_two(bvconst64_term_desc(tbl, t2));
5174 if (k >= 0) {
5175 return bvrem_power(manager, t1, k);
5176 }
5177 break;
5178
5179 case BV_CONSTANT:
5180 if (term_kind(tbl, t1) == BV_CONSTANT) {
5181 return bvrem_const(manager, bvconst_term_desc(tbl, t1), bvconst_term_desc(tbl, t2));
5182 }
5183 k = bvconst_term_is_power_of_two(bvconst_term_desc(tbl, t2));
5184 if (k >= 0) {
5185 return bvrem_power(manager, t1, k);
5186 }
5187 break;
5188
5189 default:
5190 break;
5191 }
5192
5193 return bvrem_term(tbl, t1, t2);
5194 }
5195
5196
5197 /*
5198 * SIGNED DIVISION: QUOTIENT
5199 */
bvsdiv_const64(term_manager_t * manager,bvconst64_term_t * a,bvconst64_term_t * b)5200 static term_t bvsdiv_const64(term_manager_t *manager, bvconst64_term_t *a, bvconst64_term_t *b) {
5201 uint64_t x;
5202 uint32_t n;
5203
5204 n = a->bitsize;
5205 assert(n == b->bitsize);
5206 x = bvconst64_sdiv2z(a->value, b->value, n);
5207 assert(x == norm64(x, n));
5208
5209 return bv64_constant(manager->terms, n, x);
5210 }
5211
bvsdiv_const(term_manager_t * manager,bvconst_term_t * a,bvconst_term_t * b)5212 static term_t bvsdiv_const(term_manager_t *manager, bvconst_term_t *a, bvconst_term_t *b) {
5213 bvconstant_t *bv;
5214 uint32_t n;
5215
5216 n = a->bitsize;
5217 assert(n == b->bitsize && n > 64);
5218
5219 bv = &manager->bv0;
5220
5221 bvconstant_set_bitsize(bv, n);
5222 bvconst_sdiv2z(bv->data, n, a->data, b->data);
5223 bvconst_normalize(bv->data, n);
5224
5225 return bvconst_term(manager->terms, n, bv->data);
5226 }
5227
mk_bvsdiv(term_manager_t * manager,term_t t1,term_t t2)5228 term_t mk_bvsdiv(term_manager_t *manager, term_t t1, term_t t2) {
5229 term_table_t *tbl;
5230
5231 tbl = manager->terms;
5232
5233 assert(is_bitvector_term(tbl, t1) && is_bitvector_term(tbl, t2)
5234 && term_type(tbl, t1) == term_type(tbl, t2));
5235
5236 switch (term_kind(tbl, t2)) {
5237 case BV64_CONSTANT:
5238 if (term_kind(tbl, t1) == BV64_CONSTANT) {
5239 return bvsdiv_const64(manager, bvconst64_term_desc(tbl, t1), bvconst64_term_desc(tbl, t2));
5240 }
5241 break;
5242
5243 case BV_CONSTANT:
5244 if (term_kind(tbl, t1) == BV_CONSTANT) {
5245 return bvsdiv_const(manager, bvconst_term_desc(tbl, t1), bvconst_term_desc(tbl, t2));
5246 }
5247 break;
5248
5249 default:
5250 break;
5251 }
5252
5253 return bvsdiv_term(tbl, t1, t2);
5254 }
5255
5256
5257 /*
5258 * SIGNED DIVISION: REMAINDER (ROUNDING TO 0)
5259 */
bvsrem_const64(term_manager_t * manager,bvconst64_term_t * a,bvconst64_term_t * b)5260 static term_t bvsrem_const64(term_manager_t *manager, bvconst64_term_t *a, bvconst64_term_t *b) {
5261 uint64_t x;
5262 uint32_t n;
5263
5264 n = a->bitsize;
5265 assert(n == b->bitsize);
5266 x = bvconst64_srem2z(a->value, b->value, n);
5267 assert(x == norm64(x, n));
5268
5269 return bv64_constant(manager->terms, n, x);
5270 }
5271
bvsrem_const(term_manager_t * manager,bvconst_term_t * a,bvconst_term_t * b)5272 static term_t bvsrem_const(term_manager_t *manager, bvconst_term_t *a, bvconst_term_t *b) {
5273 bvconstant_t *bv;
5274 uint32_t n;
5275
5276 n = a->bitsize;
5277 assert(n == b->bitsize && n > 64);
5278
5279 bv = &manager->bv0;
5280
5281 bvconstant_set_bitsize(bv, n);
5282 bvconst_srem2z(bv->data, n, a->data, b->data);
5283 bvconst_normalize(bv->data, n);
5284
5285 return bvconst_term(manager->terms, n, bv->data);
5286 }
5287
mk_bvsrem(term_manager_t * manager,term_t t1,term_t t2)5288 term_t mk_bvsrem(term_manager_t *manager, term_t t1, term_t t2) {
5289 term_table_t *tbl;
5290
5291 tbl = manager->terms;
5292
5293 assert(is_bitvector_term(tbl, t1) && is_bitvector_term(tbl, t2)
5294 && term_type(tbl, t1) == term_type(tbl, t2));
5295
5296 switch (term_kind(tbl, t2)) {
5297 case BV64_CONSTANT:
5298 if (term_kind(tbl, t1) == BV64_CONSTANT) {
5299 return bvsrem_const64(manager, bvconst64_term_desc(tbl, t1), bvconst64_term_desc(tbl, t2));
5300 }
5301 break;
5302
5303 case BV_CONSTANT:
5304 if (term_kind(tbl, t1) == BV_CONSTANT) {
5305 return bvsrem_const(manager, bvconst_term_desc(tbl, t1), bvconst_term_desc(tbl, t2));
5306 }
5307 break;
5308
5309 default:
5310 break;
5311 }
5312
5313 return bvsrem_term(tbl, t1, t2);
5314 }
5315
5316
5317 /*
5318 * FLOOR DIVISION: REMAINDER (ROUNDING TO - INFINITY)
5319 */
bvsmod_const64(term_manager_t * manager,bvconst64_term_t * a,bvconst64_term_t * b)5320 static term_t bvsmod_const64(term_manager_t *manager, bvconst64_term_t *a, bvconst64_term_t *b) {
5321 uint64_t x;
5322 uint32_t n;
5323
5324 n = a->bitsize;
5325 assert(n == b->bitsize);
5326 x = bvconst64_smod2z(a->value, b->value, n);
5327 assert(x == norm64(x, n));
5328
5329 return bv64_constant(manager->terms, n, x);
5330 }
5331
bvsmod_const(term_manager_t * manager,bvconst_term_t * a,bvconst_term_t * b)5332 static term_t bvsmod_const(term_manager_t *manager, bvconst_term_t *a, bvconst_term_t *b) {
5333 bvconstant_t *bv;
5334 uint32_t n;
5335
5336 n = a->bitsize;
5337 assert(n == b->bitsize && n > 64);
5338
5339 bv = &manager->bv0;
5340
5341 bvconstant_set_bitsize(bv, n);
5342 bvconst_smod2z(bv->data, n, a->data, b->data);
5343 bvconst_normalize(bv->data, n);
5344
5345 return bvconst_term(manager->terms, n, bv->data);
5346 }
5347
5348
mk_bvsmod(term_manager_t * manager,term_t t1,term_t t2)5349 term_t mk_bvsmod(term_manager_t *manager, term_t t1, term_t t2) {
5350 term_table_t *tbl;
5351
5352 tbl = manager->terms;
5353
5354 assert(is_bitvector_term(tbl, t1) && is_bitvector_term(tbl, t2)
5355 && term_type(tbl, t1) == term_type(tbl, t2));
5356
5357 switch (term_kind(tbl, t2)) {
5358 case BV64_CONSTANT:
5359 if (term_kind(tbl, t1) == BV64_CONSTANT) {
5360 return bvsmod_const64(manager, bvconst64_term_desc(tbl, t1), bvconst64_term_desc(tbl, t2));
5361 }
5362 break;
5363
5364 case BV_CONSTANT:
5365 if (term_kind(tbl, t1) == BV_CONSTANT) {
5366 return bvsmod_const(manager, bvconst_term_desc(tbl, t1), bvconst_term_desc(tbl, t2));
5367 }
5368 break;
5369
5370 default:
5371 break;
5372 }
5373
5374 return bvsmod_term(tbl, t1, t2);
5375 }
5376
5377
5378
5379
5380 /*****************
5381 * BIT EXTRACT *
5382 ****************/
5383
5384 /*
5385 * Extract bit i of t
5386 * - t must be a bitvector term
5387 * - i must be between 0 and n-1, where n = bitsize of t
5388 *
5389 * The result is a boolean term
5390 */
mk_bitextract(term_manager_t * manager,term_t t,uint32_t i)5391 term_t mk_bitextract(term_manager_t *manager, term_t t, uint32_t i) {
5392 term_table_t *tbl;
5393 bvconst64_term_t *d;
5394 bvconst_term_t *c;
5395 composite_term_t *bv;
5396 term_t u;
5397
5398 tbl = manager->terms;
5399
5400 assert(is_bitvector_term(tbl, t) && 0 <= i && i < term_bitsize(tbl, t));
5401
5402 switch (term_kind(tbl, t)) {
5403 case BV64_CONSTANT:
5404 d = bvconst64_term_desc(tbl, t);
5405 u = bool2term(tst_bit64(d->value, i));
5406 break;
5407
5408 case BV_CONSTANT:
5409 c = bvconst_term_desc(tbl, t);
5410 u = bool2term(bvconst_tst_bit(c->data, i));
5411 break;
5412
5413 case BV_ARRAY:
5414 bv = bvarray_term_desc(tbl, t);
5415 u = bv->arg[i];
5416 break;
5417
5418 default:
5419 u = bit_term(tbl, i, t);
5420 break;
5421 }
5422
5423 return u;
5424 }
5425
5426
5427 /*
5428 * Convert bit i of buffer b to a term then reset b
5429 */
bvl_get_bit(term_manager_t * manager,bvlogic_buffer_t * b,uint32_t i)5430 term_t bvl_get_bit(term_manager_t *manager, bvlogic_buffer_t *b, uint32_t i) {
5431 term_t t;
5432
5433 assert(i < b->bitsize);
5434 t = map_bit_to_term(manager, b->bit[i]);
5435 bvlogic_buffer_clear(b);
5436
5437 return t;
5438 }
5439
5440
5441
5442
5443
5444
5445 /**********************
5446 * BIT-VECTOR ATOMS *
5447 *********************/
5448
5449 /*
5450 * For debugging: check that t1 and t2 are bitvectors terms of the same size
5451 */
5452 #ifndef NDEBUG
5453
valid_bvcomp(term_table_t * tbl,term_t t1,term_t t2)5454 static bool valid_bvcomp(term_table_t *tbl, term_t t1, term_t t2) {
5455 return is_bitvector_term(tbl, t1) && is_bitvector_term(tbl, t2)
5456 && term_type(tbl, t1) == term_type(tbl, t2);
5457 }
5458
5459 #endif
5460
5461
5462 /*
5463 * Unsigned comparison
5464 */
5465
5466 // check whether t1 < t2 holds trivially
must_lt(term_manager_t * manager,term_t t1,term_t t2)5467 static bool must_lt(term_manager_t *manager, term_t t1, term_t t2) {
5468 bvconstant_t *bv1, *bv2;
5469
5470 bv1 = &manager->bv1;
5471 bv2 = &manager->bv2;
5472 upper_bound_unsigned(manager->terms, t1, bv1); // t1 <= bv1
5473 lower_bound_unsigned(manager->terms, t2, bv2); // bv2 <= t2
5474 assert(bv1->bitsize == bv2->bitsize);
5475
5476 return bvconst_lt(bv1->data, bv2->data, bv1->bitsize);
5477 }
5478
5479 // check whether t1 <= t2 holds trivially
must_le(term_manager_t * manager,term_t t1,term_t t2)5480 static bool must_le(term_manager_t *manager, term_t t1, term_t t2) {
5481 bvconstant_t *bv1, *bv2;
5482
5483 bv1 = &manager->bv1;
5484 bv2 = &manager->bv2;
5485 upper_bound_unsigned(manager->terms, t1, bv1);
5486 lower_bound_unsigned(manager->terms, t2, bv2);
5487 assert(bv1->bitsize == bv2->bitsize);
5488
5489 return bvconst_le(bv1->data, bv2->data, bv1->bitsize);
5490 }
5491
5492 // t1 >= t2: unsigned
mk_bvge(term_manager_t * manager,term_t t1,term_t t2)5493 term_t mk_bvge(term_manager_t *manager, term_t t1, term_t t2) {
5494 assert(valid_bvcomp(manager->terms, t1, t2));
5495
5496 if (t1 == t2 || must_le(manager, t2, t1)) {
5497 return true_term;
5498 }
5499
5500 if (must_lt(manager, t1, t2)) {
5501 return false_term;
5502 }
5503
5504 if (bvterm_is_min_unsigned(manager->terms, t1)) {
5505 // 0b0000..00 >= t2 iff t2 == 0b0000..00
5506 return mk_bitvector_eq(manager, t1, t2);
5507 }
5508
5509 if (bvterm_is_max_unsigned(manager->terms, t2)) {
5510 // t1 >= 0b1111..11 iff t1 == 0b1111..11
5511 return mk_bitvector_eq(manager, t1, t2);
5512 }
5513
5514 return bvge_atom(manager->terms, t1, t2);
5515 }
5516
5517 // t1 > t2: unsigned
mk_bvgt(term_manager_t * manager,term_t t1,term_t t2)5518 term_t mk_bvgt(term_manager_t *manager, term_t t1, term_t t2) {
5519 return opposite_term(mk_bvge(manager, t2, t1));
5520 }
5521
5522 // t1 <= t2: unsigned
mk_bvle(term_manager_t * manager,term_t t1,term_t t2)5523 term_t mk_bvle(term_manager_t *manager, term_t t1, term_t t2) {
5524 return mk_bvge(manager, t2, t1);
5525 }
5526
5527 // t1 < t2: unsigned
mk_bvlt(term_manager_t * manager,term_t t1,term_t t2)5528 term_t mk_bvlt(term_manager_t *manager, term_t t1, term_t t2) {
5529 return opposite_term(mk_bvge(manager, t1, t2));
5530 }
5531
5532
5533
5534
5535 /*
5536 * Signed comparisons
5537 */
5538
5539 // Check whether t1 < t2 holds trivially
must_slt(term_manager_t * manager,term_t t1,term_t t2)5540 static bool must_slt(term_manager_t *manager, term_t t1, term_t t2) {
5541 bvconstant_t *bv1, *bv2;
5542
5543 bv1 = &manager->bv1;
5544 bv2 = &manager->bv2;
5545 upper_bound_signed(manager->terms, t1, bv1);
5546 lower_bound_signed(manager->terms, t2, bv2);
5547 assert(bv1->bitsize == bv2->bitsize);
5548
5549 return bvconst_slt(bv1->data, bv2->data, bv1->bitsize);
5550 }
5551
5552 // Check whether t1 <= t2 holds
must_sle(term_manager_t * manager,term_t t1,term_t t2)5553 static bool must_sle(term_manager_t *manager, term_t t1, term_t t2) {
5554 bvconstant_t *bv1, *bv2;
5555
5556 bv1 = &manager->bv1;
5557 bv2 = &manager->bv2;
5558 upper_bound_signed(manager->terms, t1, bv1);
5559 lower_bound_signed(manager->terms, t2, bv2);
5560 assert(bv1->bitsize == bv2->bitsize);
5561
5562 return bvconst_sle(bv1->data, bv2->data, bv1->bitsize);
5563 }
5564
5565 // t1 >= t2: signed
mk_bvsge(term_manager_t * manager,term_t t1,term_t t2)5566 term_t mk_bvsge(term_manager_t *manager, term_t t1, term_t t2) {
5567 assert(valid_bvcomp(manager->terms, t1, t2));
5568
5569 if (t1 == t2 || must_sle(manager, t2, t1)) {
5570 return true_term;
5571 }
5572
5573 if (must_slt(manager, t1, t2)) {
5574 return false_term;
5575 }
5576
5577 if (bvterm_is_min_signed(manager->terms, t1)) {
5578 // 0b1000..00 >= t2 iff t2 == 0b1000..00
5579 return mk_bitvector_eq(manager, t1, t2);
5580 }
5581
5582 if (bvterm_is_max_signed(manager->terms, t2)) {
5583 // t1 >= 0b0111..11 iff t1 == 0b0111..11
5584 return mk_bitvector_eq(manager, t1, t2);
5585 }
5586
5587 return bvsge_atom(manager->terms, t1, t2);
5588 }
5589
5590 // t1 > t2: signed
mk_bvsgt(term_manager_t * manager,term_t t1,term_t t2)5591 term_t mk_bvsgt(term_manager_t *manager, term_t t1, term_t t2) {
5592 return opposite_term(mk_bvsge(manager, t2, t1));
5593 }
5594
5595
5596 // t1 <= t2: signed
mk_bvsle(term_manager_t * manager,term_t t1,term_t t2)5597 term_t mk_bvsle(term_manager_t *manager, term_t t1, term_t t2) {
5598 return mk_bvsge(manager, t2, t1);
5599 }
5600
5601 // t1 < t2: signed
mk_bvslt(term_manager_t * manager,term_t t1,term_t t2)5602 term_t mk_bvslt(term_manager_t *manager, term_t t1, term_t t2) {
5603 return opposite_term(mk_bvsge(manager, t1, t2));
5604 }
5605
5606
5607
5608
5609 /*************************************
5610 * POWER-PRODUCTS AND POLYNOMIALS *
5611 ************************************/
5612
5613 /*
5614 * Arithmetic product:
5615 * - p is a power product descriptor: t_0^e_0 ... t_{n-1}^e_{n-1}
5616 * - a is an array of n arithmetic terms
5617 * - this function constructs the term a[0]^e_0 ... a[n-1]^e_{n-1}
5618 */
mk_arith_pprod(term_manager_t * mngr,pprod_t * p,uint32_t n,const term_t * a)5619 term_t mk_arith_pprod(term_manager_t *mngr, pprod_t *p, uint32_t n, const term_t *a) {
5620 rba_buffer_t *b;
5621 term_table_t *tbl;
5622 uint32_t i;
5623
5624 assert(n == p->len);
5625
5626 tbl = term_manager_get_terms(mngr);
5627 b = term_manager_get_arith_buffer(mngr);
5628
5629 rba_buffer_set_one(b); // b := 1
5630 for (i=0; i<n; i++) {
5631 // b := b * a[i]^e[i]
5632 rba_buffer_mul_term_power(b, tbl, a[i], p->prod[i].exp);
5633 }
5634
5635 return mk_arith_term(mngr, b);
5636 }
5637
5638
5639 /*
5640 * Bitvector product: 1 to 64 bits vector
5641 * - p is a power product descriptor: t_0^e_0 ... t_{n-1}^e_{n-1}
5642 * - a is an array of n bitvector terms
5643 * - nbits = number of bits in each term of a
5644 * - this function constructs the term a[0]^e_0 ... a[n-1]^e_{n-1}
5645 */
mk_bvarith64_pprod(term_manager_t * mngr,pprod_t * p,uint32_t n,const term_t * a,uint32_t nbits)5646 term_t mk_bvarith64_pprod(term_manager_t *mngr, pprod_t *p, uint32_t n, const term_t *a, uint32_t nbits) {
5647 bvarith64_buffer_t *b;
5648 term_table_t *tbl;
5649 uint32_t i;
5650
5651 assert(n == p->len && 0 < nbits && nbits <= 64);
5652
5653 tbl = term_manager_get_terms(mngr);
5654 b = term_manager_get_bvarith64_buffer(mngr);
5655
5656 bvarith64_buffer_prepare(b, nbits);
5657 bvarith64_buffer_set_one(b); // b := 1
5658 for (i=0; i<n; i++) {
5659 // b := b * a[i]^e[i]
5660 bvarith64_buffer_mul_term_power(b, tbl, a[i], p->prod[i].exp);
5661 }
5662
5663 return mk_bvarith64_term(mngr, b);
5664 }
5665
5666
5667 /*
5668 * Bitvector product: more than 64 bits
5669 * - p is a power product descriptor: t_0^e_0 ... t_{n-1}^e_{n-1}
5670 * - a is an array of n bitvector terms
5671 * - nbits = number of bits in each term of a
5672 * - this function constructs the term a[0]^e_0 ... a[n-1]^e_{n-1}
5673 */
mk_bvarith_pprod(term_manager_t * mngr,pprod_t * p,uint32_t n,const term_t * a,uint32_t nbits)5674 term_t mk_bvarith_pprod(term_manager_t *mngr, pprod_t *p, uint32_t n, const term_t *a, uint32_t nbits) {
5675 bvarith_buffer_t *b;
5676 term_table_t *tbl;
5677 uint32_t i;
5678
5679 assert(n == p->len && 64 < nbits && nbits <= YICES_MAX_BVSIZE);
5680
5681 tbl = term_manager_get_terms(mngr);
5682 b = term_manager_get_bvarith_buffer(mngr);
5683
5684 bvarith_buffer_prepare(b, nbits);
5685 bvarith_buffer_set_one(b); // b := 1
5686 for (i=0; i<n; i++) {
5687 // b := b * a[i]^e[i]
5688 bvarith_buffer_mul_term_power(b, tbl, a[i], p->prod[i].exp);
5689 }
5690
5691 return mk_bvarith_term(mngr, b);
5692 }
5693
5694
5695 /*
5696 * Generic version: check the type of a[0]
5697 */
mk_pprod(term_manager_t * mngr,pprod_t * p,uint32_t n,const term_t * a)5698 term_t mk_pprod(term_manager_t *mngr, pprod_t *p, uint32_t n, const term_t *a) {
5699 type_t tau;
5700 uint32_t nbits;
5701
5702 assert(n > 0);
5703
5704 tau = term_type(mngr->terms, a[0]);
5705 if (is_arithmetic_type(tau)) {
5706 return mk_arith_pprod(mngr, p, n, a);
5707 } else {
5708 nbits = bv_type_size(mngr->types, tau);
5709 if (nbits <= 64) {
5710 return mk_bvarith64_pprod(mngr, p, n, a, nbits);
5711 } else {
5712 return mk_bvarith_pprod(mngr, p, n, a, nbits);
5713 }
5714 }
5715 }
5716
5717 /*
5718 * Polynomial:
5719 * - p is a polynomial c_0 t_0 + c_1 t_1 + ... + c_{n-1} t_{n-1}
5720 * - a is an array of n terms
5721 * - construct the term c_0 a[0] + c_1 a[1] + ... + c_{n-1} a[n-1]
5722 * except that c_i * a[i] is replaced by c_i if a[i] == const_idx.
5723 */
mk_arith_poly(term_manager_t * mngr,polynomial_t * p,uint32_t n,const term_t * a)5724 term_t mk_arith_poly(term_manager_t *mngr, polynomial_t *p, uint32_t n, const term_t *a) {
5725 rba_buffer_t *b;
5726 term_table_t *tbl;
5727 uint32_t i;
5728
5729 assert(p->nterms == n);
5730
5731 tbl = term_manager_get_terms(mngr);
5732 b = term_manager_get_arith_buffer(mngr);
5733 reset_rba_buffer(b);
5734
5735 for (i=0; i<n; i++) {
5736 if (a[i] == const_idx) {
5737 rba_buffer_add_const(b, &p->mono[i].coeff);
5738 } else {
5739 rba_buffer_add_const_times_term(b, tbl, &p->mono[i].coeff, a[i]);
5740 }
5741 }
5742
5743 return mk_arith_term(mngr, b);
5744 }
5745
5746
5747 /*
5748 * Same thing for a bitvector polynomial (1 to 64bits)
5749 */
mk_bvarith64_poly(term_manager_t * mngr,bvpoly64_t * p,uint32_t n,const term_t * a)5750 term_t mk_bvarith64_poly(term_manager_t *mngr, bvpoly64_t *p, uint32_t n, const term_t *a) {
5751 bvarith64_buffer_t *b;
5752 term_table_t *tbl;
5753 uint32_t i;
5754
5755 assert(p->nterms == n && 0 < p->bitsize && p->bitsize <= 64);
5756
5757 tbl = term_manager_get_terms(mngr);
5758 b = term_manager_get_bvarith64_buffer(mngr);
5759 bvarith64_buffer_prepare(b, p->bitsize);
5760
5761 for (i=0; i<n; i++) {
5762 if (a[i] == const_idx) {
5763 bvarith64_buffer_add_const(b, p->mono[i].coeff);
5764 } else {
5765 bvarith64_buffer_add_const_times_term(b, tbl, p->mono[i].coeff, a[i]);
5766 }
5767 }
5768
5769 return mk_bvarith64_term(mngr, b);
5770 }
5771
5772
5773 /*
5774 * Same thing for a bitvector polynomial (more than 64bits)
5775 */
mk_bvarith_poly(term_manager_t * mngr,bvpoly_t * p,uint32_t n,const term_t * a)5776 term_t mk_bvarith_poly(term_manager_t *mngr, bvpoly_t *p, uint32_t n, const term_t *a) {
5777 bvarith_buffer_t *b;
5778 term_table_t *tbl;
5779 uint32_t i;
5780
5781 assert(p->nterms == n && 64 < p->bitsize && p->bitsize <= YICES_MAX_BVSIZE);
5782
5783 tbl = term_manager_get_terms(mngr);
5784 b = term_manager_get_bvarith_buffer(mngr);
5785 bvarith_buffer_prepare(b, p->bitsize);
5786
5787 for (i=0; i<n; i++) {
5788 if (a[i] == const_idx) {
5789 bvarith_buffer_add_const(b, p->mono[i].coeff);
5790 } else {
5791 bvarith_buffer_add_const_times_term(b, tbl, p->mono[i].coeff, a[i]);
5792 }
5793 }
5794
5795 return mk_bvarith_term(mngr, b);
5796 }
5797
5798
5799
5800 /*
5801 * Support for eliminating arithmetic variables:
5802 * - given a polynomial p and a term t that occurs in p
5803 * - construct the polynomial q such that (t == q) is equivalent to (p == 0)
5804 * (i.e., write p as a.t + r and construct q := -r/a).
5805 */
mk_arith_elim_poly(term_manager_t * mngr,polynomial_t * p,term_t t)5806 term_t mk_arith_elim_poly(term_manager_t *mngr, polynomial_t *p, term_t t) {
5807 rba_buffer_t *b;
5808 rational_t *a;
5809 uint32_t i, j, n;
5810
5811 assert(good_term(mngr->terms, t));
5812
5813 n = p->nterms;
5814
5815 // find j such that p->mono[j].var == t
5816 j = 0;
5817 while (p->mono[j].var != t) {
5818 j++;
5819 assert(j < n);
5820 }
5821
5822 a = &p->mono[j].coeff; // coefficient of t in p
5823 assert(q_is_nonzero(a));
5824
5825 /*
5826 * p is r + a.t, construct -r/a in buffer b
5827 */
5828 b = term_manager_get_arith_buffer(mngr);
5829 reset_rba_buffer(b);
5830 if (q_is_minus_one(a)) {
5831 // special case: a = -1
5832 i = 0;
5833 if (p->mono[0].var == const_idx) {
5834 assert(j > 0);
5835 rba_buffer_add_const(b, &p->mono[0].coeff);
5836 i ++;
5837 }
5838 while (i < n) {
5839 if (i != j) {
5840 assert(p->mono[i].var != t);
5841 rba_buffer_add_varmono(b, &p->mono[i].coeff, p->mono[i].var);
5842 }
5843 i++;
5844 }
5845 } else {
5846 // first construct -r then divide by a
5847 i = 0;
5848 if (p->mono[0].var == const_idx) {
5849 assert(j > 0);
5850 rba_buffer_sub_const(b, &p->mono[0].coeff);
5851 i ++;
5852 }
5853 while (i < n) {
5854 if (i != j) {
5855 assert(p->mono[i].var != t);
5856 rba_buffer_sub_varmono(b, &p->mono[i].coeff, p->mono[i].var);
5857 }
5858 i ++;
5859 }
5860 if (! q_is_one(a)) {
5861 rba_buffer_div_const(b, a);
5862 }
5863 }
5864
5865 return mk_arith_term(mngr, b);
5866 }
5867
5868