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