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  * UTILITIES TO ACCESS CONTEXT STRUCTURES
21  */
22 
23 #ifndef __CONTEXT_UTILS_H
24 #define __CONTEXT_UTILS_H
25 
26 #include "context/context_types.h"
27 
28 
29 /*
30  * SUBST AND MARK VECTOR
31  */
32 
33 /*
34  * If variable elimination is enabled, then ctx->subst is used to
35  * store candidate substitutions before we check for substitution
36  * cycles. The mark vector is used to mark terms during cycle detection.
37  */
38 
39 /*
40  * Return ctx->subst. Allocate and initialize it if necessary.
41  */
42 extern pseudo_subst_t *context_get_subst(context_t *ctx);
43 
44 /*
45  * Free ctx->subst (if it's not NULL)
46  */
47 extern void context_free_subst(context_t *ctx);
48 
49 
50 /*
51  * Return ctx->marks. Allocate and initialize it if necessary.
52  */
53 extern mark_vector_t *context_get_marks(context_t *ctx);
54 
55 
56 /*
57  * Free the mark vector if non-NULL
58  */
59 extern void context_free_marks(context_t *ctx);
60 
61 
62 /*
63  * INTERNAL CACHES AND AUXILIARY STRUCTURES
64  */
65 
66 /*
67  * There are two internal caches for visiting terms.
68  * - the 'cache' uses a bitvector implementation and should be
69  *   better for operations that visit many terms.
70  * - the 'small_cache' uses a hash table and should be better
71  *   for operations that visit a small number of terms.
72  *
73  * There are three buffers for internal construction of polynomials
74  * - arith_buffer is more expensive (requires more memory) but
75  *   it supports more operations (e.g., term constructors in yices_api.c
76  *   take arith_buffers as arguments).
77  * - poly_buffer is a cheaper data structure, but it does not support
78  *   all the operations
79  * - aux_poly is even cheaper, but it's for direct construction only
80  *
81  * There's one buffer for bitvector polynomials. It's suitable for all
82  * bit widths.
83  */
84 
85 /*
86  * Allocate/reset/free the small cache
87  * - the cache is allocated and initialized on the first call to get_small_cache
88  * - reset and free do nothing if the cache is not allocated
89  */
90 extern int_hset_t *context_get_small_cache(context_t *ctx);
91 extern void context_reset_small_cache(context_t *ctx);
92 extern void context_free_small_cache(context_t *ctx);
93 
94 
95 /*
96  * Allocate/free the cache
97  * - same conventions as for the small_cache
98  */
99 extern int_bvset_t *context_get_cache(context_t *ctx);
100 extern void context_free_cache(context_t *ctx);
101 
102 
103 /*
104  * Buffers for polynomials
105  */
106 extern rba_buffer_t *context_get_arith_buffer(context_t *ctx);
107 extern void context_free_arith_buffer(context_t *ctx);
108 
109 extern poly_buffer_t *context_get_poly_buffer(context_t *ctx);
110 extern void context_free_poly_buffer(context_t *ctx);
111 extern void context_reset_poly_buffer(context_t *ctx);
112 
113 
114 /*
115  * Allocate the auxiliary polynomial buffer and make it large enough
116  * for n monomials.
117  */
118 extern polynomial_t *context_get_aux_poly(context_t *ctx, uint32_t n);
119 
120 /*
121  * Free the auxiliary polynomial
122  */
123 extern void context_free_aux_poly(context_t *ctx);
124 
125 
126 /*
127  * Buffers for bitvector polynomials
128  */
129 extern bvpoly_buffer_t *context_get_bvpoly_buffer(context_t *ctx);
130 extern void context_free_bvpoly_buffer(context_t *ctx);
131 
132 
133 
134 /*
135  * EQUALITY CACHE
136  */
137 
138 /*
139  * If lift-if is enabled then arithmetic equalities
140  *  (eq (ite c t1 t2) u) are rewritten to (ite c (eq t1 u) (eq t2 u))
141  * We don't create new terms (eq t1 u) or (eq t2 u). Instead, we store
142  * the internalization of equalities (eq t1 u) in the eq_cache:
143  * This cache maps pairs of terms <t, u> to a literal l (such that
144  * l is the internalization of (t == u)).
145  *
146  * The following functions operate on this cache: reset/free/push/pop
147  * do nothing if the cache does not exist.
148  */
149 extern pmap2_t *context_get_eq_cache(context_t *ctx);
150 extern void context_free_eq_cache(context_t *ctx);
151 extern void context_eq_cache_push(context_t *ctx);
152 extern void context_eq_cache_pop(context_t *ctx);
153 
context_reset_eq_cache(context_t * ctx)154 static inline void context_reset_eq_cache(context_t *ctx) {
155   context_free_eq_cache(ctx);
156 }
157 
158 
159 /*
160  * Check what's mapped to (t1, t2) in the internal eq_cache.
161  * - return null_literal if nothing is mapped to (t1, t2) (or if the cache does not exit)
162  */
163 extern literal_t find_in_eq_cache(context_t *ctx, term_t t1, term_t t2);
164 
165 
166 /*
167  * Add the mapping (t1, t2) --> l to the equality cache.
168  * - allocate and initialize the cache if needed.
169  * - the pair (t1, t2) must not be in the cache already.
170  * - l must be different from null_literal
171  */
172 extern void add_to_eq_cache(context_t *ctx, term_t t1, term_t t2, literal_t l);
173 
174 
175 
176 /*
177  * DIV/MOD TABLE
178  */
179 
180 /*
181  * Initialization/reset/deletion and push/pop
182  * - get_divmod_table allocates and initializes the table if needed.
183  * - free/reset/push/pop do nothing if the table does not exist.
184  */
185 extern divmod_tbl_t *context_get_divmod_table(context_t *ctx);
186 extern void context_free_divmod_table(context_t *ctx);
187 extern void context_reset_divmod_table(context_t *ctx);
188 extern void context_divmod_table_push(context_t *ctx);
189 extern void context_divmod_table_pop(context_t *ctx);
190 
191 
192 /*
193  * Check whether the record for (floor x) is in the table.
194  * If so return the theory variable mapped to (floor x).
195  * If not return null_thvar
196  * Also returns null_thvar if the table does not exist.
197  */
198 extern thvar_t context_find_var_for_floor(context_t *ctx, thvar_t x);
199 
200 
201 /*
202  * Check whether the record for (ceil x) is in the table.
203  * If so return the theory variable mapped to (ceil x).
204  * If not return null_thvar
205  * Also returns null_thvar if the table does not exist.
206  */
207 extern thvar_t context_find_var_for_ceil(context_t *ctx, thvar_t x);
208 
209 /*
210  * Check whether the record for (div x k) is in the table.
211  * If so return the theory variable mapped to (div x k).
212  * If not return null_thvar.
213  * Also returns null_thvar if the table does not exist.
214  */
215 extern thvar_t context_find_var_for_div(context_t *ctx, thvar_t x, const rational_t *k);
216 
217 
218 /*
219  * Add record for (floor x):
220  * - y = theory variable for (floor x)
221  * - this creates the table if needed.
222  */
223 extern void context_record_floor(context_t *ctx, thvar_t x, thvar_t y);
224 
225 
226 /*
227  * Same thing for (ceil x)
228  * - y = theory variable for (ceil x)
229  */
230 extern void context_record_ceil(context_t *ctx, thvar_t x, thvar_t y);
231 
232 
233 /*
234  * Same thing for (div x k)
235  * - y = theory variable for (div x k)
236  */
237 extern void context_record_div(context_t *ctx, thvar_t x, const rational_t *k, thvar_t y);
238 
239 
240 
241 
242 /*
243  * FACTORING OF DISJUNCTS
244  */
245 
246 /*
247  * Return the explorer data structure
248  * - allocate and initialize it if needed
249  */
250 extern bfs_explorer_t *context_get_explorer(context_t *ctx);
251 
252 /*
253  * Free the explorer if it's not NULL
254  */
255 extern void context_free_explorer(context_t *ctx);
256 
257 /*
258  * Reset it if it's not NULL
259  */
260 extern void context_reset_explorer(context_t *ctx);
261 
262 /*
263  * Get the common factors of term t
264  * - this checks whether t is of the form (or (and  ..) (and ..) ...))
265  *   and stores all terms that occur in each conjuncts into vector v
266  * - example: if t is (or (and A B) (and A C D)) then A is stored in v
267  * - if t is not (OR ...) then t is added to v
268  *
269  * This allocates and initializes ctx->explorer if needed
270  */
271 extern void context_factor_disjunction(context_t *ctx, term_t t, ivector_t *v);
272 
273 
274 /*
275  * AUXILIARY ATOMS
276  */
277 
278 /*
279  * Simplification procedures can add equalities to the aux_eq vector
280  * or atoms to the aux_atom vector. These vectors can then be processed
281  * later by the internalization/flatteining procedures.
282  */
283 
284 /*
285  * Auxiliary equalities:
286  * - add a new equality (x == y) in the aux_eq vector.
287  * - this is useful for simplification procedures that are executed after
288  *   assertion flattening (e.g., symmetry breaking).
289  * - the auxiliary equalities can then be processed by process_aux_eqs
290  */
291 extern void add_aux_eq(context_t *ctx, term_t x, term_t y);
292 
293 /*
294  * Variant: add term e as an auxiliary equality
295  * - e can be either ARITH_BINEQ_ATOM or ARITH_EQ_ATOM
296  */
297 extern void add_arith_aux_eq(context_t *ctx, term_t eq);
298 
299 
300 /*
301  * Auxiliary atoms:
302  * - add atom a to the aux_atoms vector
303  * - the auxiliary atom can be processed later by process_aux_atoms
304  */
305 extern void add_aux_atom(context_t *ctx, term_t atom);
306 
307 
308 
309 /*
310  * DIFFERENCE-LOGIC DATA
311  */
312 
313 /*
314  * Map to compute a bound on the length path:
315  * - allocate and initialize the table if needed
316  */
317 extern int_rat_hmap_t *context_get_edge_map(context_t *ctx);
318 
319 /*
320  * Delete the map
321  */
322 extern void context_free_edge_map(context_t *ctx);
323 
324 /*
325  * Difference-logic profile:
326  * - allocate and initialize the structure if it does not exist
327  */
328 extern dl_data_t *context_get_dl_profile(context_t *ctx);
329 
330 /*
331  * Free the profile record if it's not NULL
332  */
333 extern void context_free_dl_profile(context_t *ctx);
334 
335 
336 /*
337  * TESTS
338  */
339 
340 /*
341  * Check whether t is true or false (i.e., mapped to 'true_occ' or 'false_occ'
342  * in the internalization table.
343  * - t must be a root in the internalization table
344  */
345 extern bool term_is_true(context_t *ctx, term_t t);
346 extern bool term_is_false(context_t *ctx, term_t t);
347 
348 /*
349  * Check whether (or a[0] ...  a[n-1]) is true by checking whether
350  * one of the a[i] is internalized to a true term
351  */
352 extern bool disjunct_is_true(context_t *ctx, term_t *a, uint32_t n);
353 
354 /*
355  * Check whether t is not internalized and of the form (ite c a b)
356  * - takes the substitution into account
357  */
358 extern bool term_is_ite(context_t *ctx, term_t t);
359 
360 /*
361  * Given a descriptor  (ite c t e), checks whether it
362  * contains nested if-then-elses (i.e., whether t or e
363  * are themselves if-then-else terms).
364  *
365  * This takes the substitution/internalization table into account:
366  * - if t or e is already internalized, it's not considered an if-then-else
367  * - otherwise t and e are replaced by their root in the internalization
368  *   table
369  */
370 extern bool ite_is_deep(context_t *ctx, composite_term_t *ite);
371 
372 
373 
374 /*
375  * OPTIONS/SUPPORTED FEATURES
376  */
377 
378 /*
379  * Set or clear preprocessing options
380  */
enable_variable_elimination(context_t * ctx)381 static inline void enable_variable_elimination(context_t *ctx) {
382   ctx->options |= VARELIM_OPTION_MASK;
383 }
384 
disable_variable_elimination(context_t * ctx)385 static inline void disable_variable_elimination(context_t *ctx) {
386   ctx->options &= ~VARELIM_OPTION_MASK;
387 }
388 
enable_or_flattening(context_t * ctx)389 static inline void enable_or_flattening(context_t *ctx) {
390   ctx->options |= FLATTENOR_OPTION_MASK;
391 }
392 
disable_or_flattening(context_t * ctx)393 static inline void disable_or_flattening(context_t *ctx) {
394   ctx->options &= ~FLATTENOR_OPTION_MASK;
395 }
396 
enable_diseq_and_or_flattening(context_t * ctx)397 static inline void enable_diseq_and_or_flattening(context_t *ctx) {
398   ctx->options |= FLATTENOR_OPTION_MASK|FLATTENDISEQ_OPTION_MASK;
399 }
400 
disable_diseq_and_or_flattening(context_t * ctx)401 static inline void disable_diseq_and_or_flattening(context_t *ctx) {
402   ctx->options &= ~(FLATTENOR_OPTION_MASK|FLATTENDISEQ_OPTION_MASK);
403 }
404 
enable_eq_abstraction(context_t * ctx)405 static inline void enable_eq_abstraction(context_t *ctx) {
406   ctx->options |= EQABSTRACT_OPTION_MASK;
407 }
408 
disable_eq_abstraction(context_t * ctx)409 static inline void disable_eq_abstraction(context_t *ctx) {
410   ctx->options &= ~EQABSTRACT_OPTION_MASK;
411 }
412 
enable_arith_elimination(context_t * ctx)413 static inline void enable_arith_elimination(context_t *ctx) {
414   ctx->options |= ARITHELIM_OPTION_MASK;
415 }
416 
disable_arith_elimination(context_t * ctx)417 static inline void disable_arith_elimination(context_t *ctx) {
418   ctx->options &= ~ARITHELIM_OPTION_MASK;
419 }
420 
enable_keep_ite(context_t * ctx)421 static inline void enable_keep_ite(context_t *ctx) {
422   ctx->options |= KEEP_ITE_OPTION_MASK;
423 }
424 
disable_keep_ite(context_t * ctx)425 static inline void disable_keep_ite(context_t *ctx) {
426   ctx->options &= ~KEEP_ITE_OPTION_MASK;
427 }
428 
enable_bvarith_elimination(context_t * ctx)429 static inline void enable_bvarith_elimination(context_t *ctx) {
430   ctx->options |= BVARITHELIM_OPTION_MASK;
431 }
432 
disable_bvarith_elimination(context_t * ctx)433 static inline void disable_bvarith_elimination(context_t *ctx) {
434   ctx->options &= ~BVARITHELIM_OPTION_MASK;
435 }
436 
enable_symmetry_breaking(context_t * ctx)437 static inline void enable_symmetry_breaking(context_t *ctx) {
438   ctx->options |= BREAKSYM_OPTION_MASK;
439 }
440 
disable_symmetry_breaking(context_t * ctx)441 static inline void disable_symmetry_breaking(context_t *ctx) {
442   ctx->options &= ~BREAKSYM_OPTION_MASK;
443 }
444 
enable_pseudo_inverse_simplification(context_t * ctx)445 static inline void enable_pseudo_inverse_simplification(context_t *ctx) {
446   ctx->options |= PSEUDO_INVERSE_OPTION_MASK;
447 }
448 
disable_pseudo_inverse_simplification(context_t * ctx)449 static inline void disable_pseudo_inverse_simplification(context_t *ctx) {
450   ctx->options &= ~PSEUDO_INVERSE_OPTION_MASK;
451 }
452 
enable_assert_ite_bounds(context_t * ctx)453 static inline void enable_assert_ite_bounds(context_t *ctx) {
454   ctx->options |= ITE_BOUNDS_OPTION_MASK;
455 }
456 
disable_assert_ite_bounds(context_t * ctx)457 static inline void disable_assert_ite_bounds(context_t *ctx) {
458   ctx->options &= ~ITE_BOUNDS_OPTION_MASK;
459 }
460 
enable_cond_def_preprocessing(context_t * ctx)461 static inline void enable_cond_def_preprocessing(context_t *ctx) {
462   ctx->options |= CONDITIONAL_DEF_OPTION_MASK;
463 }
464 
disable_cond_def_preprocessing(context_t * ctx)465 static inline void disable_cond_def_preprocessing(context_t *ctx) {
466   ctx->options &= ~CONDITIONAL_DEF_OPTION_MASK;
467 }
468 
enable_ite_flattening(context_t * ctx)469 static inline void enable_ite_flattening(context_t *ctx) {
470   ctx->options |= FLATTEN_ITE_OPTION_MASK;
471 }
472 
disable_ite_flattening(context_t * ctx)473 static inline void disable_ite_flattening(context_t *ctx) {
474   ctx->options &= ~FLATTEN_ITE_OPTION_MASK;
475 }
476 
enable_or_factoring(context_t * ctx)477 static inline void enable_or_factoring(context_t *ctx) {
478   ctx->options |= FACTOR_OR_OPTION_MASK;
479 }
480 
disable_or_factoring(context_t * ctx)481 static inline void disable_or_factoring(context_t *ctx) {
482   ctx->options &= ~FACTOR_OR_OPTION_MASK;
483 }
484 
485 
486 
487 /*
488  * Check which options are enabled
489  */
context_var_elim_enabled(context_t * ctx)490 static inline bool context_var_elim_enabled(context_t *ctx) {
491   return (ctx->options & VARELIM_OPTION_MASK) != 0;
492 }
493 
context_flatten_or_enabled(context_t * ctx)494 static inline bool context_flatten_or_enabled(context_t *ctx) {
495   return (ctx->options & FLATTENOR_OPTION_MASK) != 0;
496 }
497 
context_flatten_diseq_enabled(context_t * ctx)498 static inline bool context_flatten_diseq_enabled(context_t *ctx) {
499   return (ctx->options & FLATTENDISEQ_OPTION_MASK) != 0;
500 }
501 
context_eq_abstraction_enabled(context_t * ctx)502 static inline bool context_eq_abstraction_enabled(context_t *ctx) {
503   return (ctx->options & EQABSTRACT_OPTION_MASK) != 0;
504 }
505 
context_arith_elim_enabled(context_t * ctx)506 static inline bool context_arith_elim_enabled(context_t *ctx) {
507   return (ctx->options & ARITHELIM_OPTION_MASK) != 0;
508 }
509 
context_keep_ite_enabled(context_t * ctx)510 static inline bool context_keep_ite_enabled(context_t *ctx) {
511   return (ctx->options & KEEP_ITE_OPTION_MASK) != 0;
512 }
513 
context_bvarith_elim_enabled(context_t * ctx)514 static inline bool context_bvarith_elim_enabled(context_t *ctx) {
515   return (ctx->options & BVARITHELIM_OPTION_MASK) != 0;
516 }
517 
context_breaksym_enabled(context_t * ctx)518 static inline bool context_breaksym_enabled(context_t *ctx) {
519   return (ctx->options & BREAKSYM_OPTION_MASK) != 0;
520 }
521 
context_pseudo_inverse_enabled(context_t * ctx)522 static inline bool context_pseudo_inverse_enabled(context_t *ctx) {
523   return (ctx->options & PSEUDO_INVERSE_OPTION_MASK) != 0;
524 }
525 
context_ite_bounds_enabled(context_t * ctx)526 static inline bool context_ite_bounds_enabled(context_t *ctx) {
527   return (ctx->options & ITE_BOUNDS_OPTION_MASK) != 0;
528 }
529 
context_cond_def_preprocessing_enabled(context_t * ctx)530 static inline bool context_cond_def_preprocessing_enabled(context_t *ctx) {
531   return (ctx->options & CONDITIONAL_DEF_OPTION_MASK) != 0;
532 }
533 
context_ite_flattening_enabled(context_t * ctx)534 static inline bool context_ite_flattening_enabled(context_t *ctx) {
535   return (ctx->options & FLATTEN_ITE_OPTION_MASK) != 0;
536 }
537 
context_or_factoring_enabled(context_t * ctx)538 static inline bool context_or_factoring_enabled(context_t *ctx) {
539   return (ctx->options & FACTOR_OR_OPTION_MASK) != 0;
540 }
541 
context_has_preprocess_options(context_t * ctx)542 static inline bool context_has_preprocess_options(context_t *ctx) {
543   return (ctx->options & PREPROCESSING_OPTIONS_MASK) != 0;
544 }
545 
context_dump_enabled(context_t * ctx)546 static inline bool context_dump_enabled(context_t *ctx) {
547   return (ctx->options & DUMP_OPTION_MASK) != 0;
548 }
549 
splx_eager_lemmas_enabled(context_t * ctx)550 static inline bool splx_eager_lemmas_enabled(context_t *ctx) {
551   return (ctx->options & SPLX_EGRLMAS_OPTION_MASK) != 0;
552 }
553 
splx_periodic_icheck_enabled(context_t * ctx)554 static inline bool splx_periodic_icheck_enabled(context_t *ctx) {
555   return (ctx->options & SPLX_ICHECK_OPTION_MASK) != 0;
556 }
557 
splx_eqprop_enabled(context_t * ctx)558 static inline bool splx_eqprop_enabled(context_t *ctx) {
559   return (ctx->options & SPLX_EQPROP_OPTION_MASK) != 0;
560 }
561 
562 
563 /*
564  * Provisional: set/clear/test dump mode
565  */
enable_dump(context_t * ctx)566 static inline void enable_dump(context_t *ctx) {
567   ctx->options |= DUMP_OPTION_MASK;
568 }
569 
disable_dump(context_t * ctx)570 static inline void disable_dump(context_t *ctx) {
571   ctx->options &= ~DUMP_OPTION_MASK;
572 }
573 
574 // Lax mode
enable_lax_mode(context_t * ctx)575 static inline void enable_lax_mode(context_t *ctx) {
576   ctx->options |= LAX_OPTION_MASK;
577 }
578 
disable_lax_mode(context_t * ctx)579 static inline void disable_lax_mode(context_t *ctx) {
580   ctx->options &= ~LAX_OPTION_MASK;
581 }
582 
context_in_strict_mode(context_t * ctx)583 static inline bool context_in_strict_mode(context_t *ctx) {
584   return (ctx->options & LAX_OPTION_MASK) == 0;
585 }
586 
587 
588 /*
589  * Supported theories
590  */
context_allows_uf(context_t * ctx)591 static inline bool context_allows_uf(context_t *ctx) {
592   return (ctx->theories & UF_MASK) != 0;
593 }
594 
context_allows_bv(context_t * ctx)595 static inline bool context_allows_bv(context_t *ctx) {
596   return (ctx->theories & BV_MASK) != 0;
597 }
598 
context_allows_idl(context_t * ctx)599 static inline bool context_allows_idl(context_t *ctx) {
600   return (ctx->theories & IDL_MASK) != 0;
601 }
602 
context_allows_rdl(context_t * ctx)603 static inline bool context_allows_rdl(context_t *ctx) {
604   return (ctx->theories & RDL_MASK) != 0;
605 }
606 
context_allows_lia(context_t * ctx)607 static inline bool context_allows_lia(context_t *ctx) {
608   return (ctx->theories & LIA_MASK) != 0;
609 }
610 
context_allows_lra(context_t * ctx)611 static inline bool context_allows_lra(context_t *ctx) {
612   return (ctx->theories & LRA_MASK) != 0;
613 }
614 
context_allows_lira(context_t * ctx)615 static inline bool context_allows_lira(context_t *ctx) {
616   return (ctx->theories & LIRA_MASK) != 0;
617 }
618 
context_allows_nlarith(context_t * ctx)619 static inline bool context_allows_nlarith(context_t *ctx) {
620   return (ctx->theories & NLIRA_MASK) != 0;
621 }
622 
context_allows_fun_updates(context_t * ctx)623 static inline bool context_allows_fun_updates(context_t *ctx) {
624   return (ctx->theories & FUN_UPDT_MASK) != 0;
625 }
626 
context_allows_extensionality(context_t * ctx)627 static inline bool context_allows_extensionality(context_t *ctx) {
628   return (ctx->theories & FUN_EXT_MASK) != 0;
629 }
630 
context_allows_quantifiers(context_t * ctx)631 static inline bool context_allows_quantifiers(context_t *ctx) {
632   return (ctx->theories & QUANT_MASK) != 0;
633 }
634 
635 
636 /*
637  * Check which solvers are present
638  */
context_has_egraph(context_t * ctx)639 static inline bool context_has_egraph(context_t *ctx) {
640   return ctx->egraph != NULL;
641 }
642 
context_has_arith_solver(context_t * ctx)643 static inline bool context_has_arith_solver(context_t *ctx) {
644   return ctx->arith_solver != NULL;
645 }
646 
context_has_bv_solver(context_t * ctx)647 static inline bool context_has_bv_solver(context_t *ctx) {
648   return ctx->bv_solver != NULL;
649 }
650 
context_has_fun_solver(context_t * ctx)651 static inline bool context_has_fun_solver(context_t *ctx) {
652   return ctx->fun_solver != NULL;
653 }
654 
context_has_mcsat(context_t * ctx)655 static inline bool context_has_mcsat(context_t *ctx) {
656   return ctx->mcsat != NULL;
657 }
658 
659 
660 /*
661  * Get the difference-logic profile record (only useful for contexts
662  * with architecture CTX_ARCH_AUTO_IDL or CTX_ARCH_AUTO_RDL).
663  */
get_diff_logic_profile(context_t * ctx)664 static inline dl_data_t *get_diff_logic_profile(context_t *ctx) {
665   return ctx->dl_profile;
666 }
667 
668 
669 /*
670  * Optional features
671  */
context_supports_multichecks(context_t * ctx)672 static inline bool context_supports_multichecks(context_t *ctx) {
673   return (ctx->options & MULTICHECKS_OPTION_MASK) != 0;
674 }
675 
context_supports_pushpop(context_t * ctx)676 static inline bool context_supports_pushpop(context_t *ctx) {
677   return (ctx->options & PUSHPOP_OPTION_MASK) != 0;
678 }
679 
context_supports_cleaninterrupt(context_t * ctx)680 static inline bool context_supports_cleaninterrupt(context_t *ctx) {
681   return (ctx->options & CLEANINT_OPTION_MASK) != 0;
682 }
683 
684 
685 /*
686  * Read the mode flag
687  */
context_get_mode(context_t * ctx)688 static inline context_mode_t context_get_mode(context_t *ctx) {
689   return ctx->mode;
690 }
691 
692 
693 #endif /* __CONTEXT_UTILS_H */
694 
695