• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SRI-CSL / yices2 / 16137379493

08 Jul 2025 07:57AM UTC coverage: 65.367% (+0.01%) from 65.357%
16137379493

push

github

web-flow
Update ci -- run coverage in pr and push (#588)


* run coverage

81222 of 124256 relevant lines covered (65.37%)

1400588.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.99
/src/mcsat/preprocessor.c
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
#if defined(CYGWIN) || defined(MINGW)
20
#ifndef __YICES_DLLSPEC__
21
#define __YICES_DLLSPEC__ __declspec(dllexport)
22
#endif
23
#endif
24

25
#include "mcsat/preprocessor.h"
26
#include "mcsat/tracing.h"
27

28
#include "terms/term_explorer.h"
29
#include "terms/bvarith64_buffer_terms.h"
30
#include "terms/bvarith_buffer_terms.h"
31

32
#include "model/models.h"
33

34
#include "context/context_types.h"
35

36
#include "yices.h"
37
#include "api/yices_api_lock_free.h"
38

39
void preprocessor_construct(preprocessor_t* pre, term_table_t* terms, jmp_buf* handler, const mcsat_options_t* options) {
635✔
40
  pre->terms = terms;
635✔
41
  init_term_manager(&pre->tm, terms);
635✔
42
  init_int_hmap(&pre->preprocess_map, 0);
635✔
43
  init_ivector(&pre->preprocess_map_list, 0);
635✔
44
  init_int_hmap(&pre->purification_map, 0);
635✔
45
  init_ivector(&pre->purification_map_list, 0);
635✔
46
  init_ivector(&pre->preprocessing_stack, 0);
635✔
47
  init_int_hmap(&pre->equalities, 0);
635✔
48
  init_ivector(&pre->equalities_list, 0);
635✔
49
  pre->tracer = NULL;
635✔
50
  pre->exception = handler;
635✔
51
  pre->options = options;
635✔
52
  scope_holder_construct(&pre->scope);
635✔
53
}
635✔
54

55
void preprocessor_set_tracer(preprocessor_t* pre, tracer_t* tracer) {
283✔
56
  pre->tracer = tracer;
283✔
57
}
283✔
58

59
void preprocessor_destruct(preprocessor_t* pre) {
635✔
60
  delete_int_hmap(&pre->purification_map);
635✔
61
  delete_ivector(&pre->purification_map_list);
635✔
62
  delete_int_hmap(&pre->preprocess_map);
635✔
63
  delete_ivector(&pre->preprocess_map_list);
635✔
64
  delete_ivector(&pre->preprocessing_stack);
635✔
65
  delete_int_hmap(&pre->equalities);
635✔
66
  delete_ivector(&pre->equalities_list);
635✔
67
  delete_term_manager(&pre->tm);
635✔
68
  scope_holder_destruct(&pre->scope);
635✔
69
}
635✔
70

71
static
72
term_t preprocessor_get(preprocessor_t* pre, term_t t) {
1,612,208✔
73
  int_hmap_pair_t* find = int_hmap_find(&pre->preprocess_map, t);
1,612,208✔
74
  if (find == NULL) {
1,612,208✔
75
    return NULL_TERM;
874,470✔
76
  } else {
77
    return find->val;
737,738✔
78
  }
79
}
80

81
static
82
void preprocessor_set(preprocessor_t* pre, term_t t, term_t t_pre) {
338,561✔
83
  assert(preprocessor_get(pre, t) == NULL_TERM);
84
  int_hmap_add(&pre->preprocess_map, t, t_pre);
338,561✔
85
  ivector_push(&pre->preprocess_map_list, t);
338,561✔
86
}
338,561✔
87

88
typedef struct composite_term1_s {
89
  uint32_t arity;  // number of subterms
90
  term_t arg[1];  // real size = arity
91
} composite_term1_t;
92

93
static
94
composite_term1_t composite_for_noncomposite;
95

96
static
97
composite_term_t* get_composite(term_table_t* terms, term_kind_t kind, term_t t) {
209,754✔
98
  assert(term_is_composite(terms, t));
99
  assert(term_kind(terms, t) == kind);
100
  assert(is_pos_term(t));
101

102
  switch (kind) {
209,754✔
103
  case ITE_TERM:           // if-then-else
20,530✔
104
  case ITE_SPECIAL:        // special if-then-else term (NEW: EXPERIMENTAL)
105
    return ite_term_desc(terms, t);
20,530✔
106
  case EQ_TERM:            // equality
20,646✔
107
    return eq_term_desc(terms, t);
20,646✔
108
  case OR_TERM:            // n-ary OR
63,869✔
109
    return or_term_desc(terms, t);
63,869✔
110
  case XOR_TERM:           // n-ary XOR
30✔
111
    return xor_term_desc(terms, t);
30✔
112
  case ARITH_BINEQ_ATOM:   // equality: (t1 == t2)  (between two arithmetic terms)
3,925✔
113
    return arith_bineq_atom_desc(terms, t);
3,925✔
114
  case ARITH_EQ_ATOM: {
3,630✔
115
    composite_for_noncomposite.arity = 1;
3,630✔
116
    composite_for_noncomposite.arg[0] = arith_eq_arg(terms, t);
3,630✔
117
    return (composite_term_t*)&composite_for_noncomposite;
3,630✔
118
  }
119
  case ARITH_GE_ATOM: {
7,933✔
120
    composite_for_noncomposite.arity = 1;
7,933✔
121
    composite_for_noncomposite.arg[0] = arith_ge_arg(terms, t);
7,933✔
122
    return (composite_term_t*)&composite_for_noncomposite;
7,933✔
123
  }
124
  case ARITH_FF_BINEQ_ATOM:
12✔
125
    return arith_ff_bineq_atom_desc(terms, t);
12✔
126
  case ARITH_FF_EQ_ATOM: {
155✔
127
    composite_for_noncomposite.arity = 1;
155✔
128
    composite_for_noncomposite.arg[0] = arith_ff_eq_arg(terms, t);
155✔
129
    return (composite_term_t*)&composite_for_noncomposite;
155✔
130
  }
131
  case APP_TERM:           // application of an uninterpreted function
5,643✔
132
    return app_term_desc(terms, t);
5,643✔
133
  case ARITH_RDIV:          // division: (/ x y)
58✔
134
    return arith_rdiv_term_desc(terms, t);
58✔
135
  case ARITH_IDIV:          // division: (div x y) as defined in SMT-LIB 2
97✔
136
    return arith_idiv_term_desc(terms, t);
97✔
137
  case ARITH_MOD:          // remainder: (mod x y) is y - x * (div x y)
158✔
138
    return arith_mod_term_desc(terms, t);
158✔
139
  case UPDATE_TERM:
2,571✔
140
    return update_term_desc(terms, t);
2,571✔
141
  case DISTINCT_TERM:
24✔
142
    return distinct_term_desc(terms, t);
24✔
143
  case BV_ARRAY:
17,561✔
144
    return bvarray_term_desc(terms, t);
17,561✔
145
  case BV_DIV:
95✔
146
    return bvdiv_term_desc(terms, t);
95✔
147
  case BV_REM:
212✔
148
    return bvrem_term_desc(terms, t);
212✔
149
  case BV_SDIV:
20✔
150
    return bvsdiv_term_desc(terms, t);
20✔
151
  case BV_SREM:
21✔
152
    return bvsrem_term_desc(terms, t);
21✔
153
  case BV_SMOD:
6✔
154
    return bvsmod_term_desc(terms, t);
6✔
155
  case BV_SHL:
143✔
156
    return bvshl_term_desc(terms, t);
143✔
157
  case BV_LSHR:
279✔
158
    return bvlshr_term_desc(terms, t);
279✔
159
  case BV_ASHR:
21✔
160
    return bvashr_term_desc(terms, t);
21✔
161
  case BV_EQ_ATOM:
58,498✔
162
    return bveq_atom_desc(terms, t);
58,498✔
163
  case BV_GE_ATOM:
2,784✔
164
    return bvge_atom_desc(terms, t);
2,784✔
165
  case BV_SGE_ATOM:
833✔
166
    return bvsge_atom_desc(terms, t);
833✔
167
  default:
×
168
    assert(false);
169
    return NULL;
×
170
  }
171
}
172

173
static
174
term_t mk_composite(preprocessor_t* pre, term_kind_t kind, uint32_t n, term_t* children) {
46,772✔
175
  term_manager_t* tm = &pre->tm;
46,772✔
176
  term_table_t* terms = pre->terms;
46,772✔
177

178
  switch (kind) {
46,772✔
179
  case ITE_TERM:           // if-then-else
12,772✔
180
  case ITE_SPECIAL:        // special if-then-else term (NEW: EXPERIMENTAL)
181
  {
182
    assert(n == 3);
183
    term_t type = super_type(pre->terms->types, term_type(terms, children[1]), term_type(terms, children[2]));
12,772✔
184
    assert(type != NULL_TYPE);
185
    return mk_ite(tm, children[0], children[1], children[2], type);
12,772✔
186
  }
187
  case EQ_TERM:            // equality
3,544✔
188
    assert(n == 2);
189
    return mk_eq(tm, children[0], children[1]);
3,544✔
190
  case OR_TERM:            // n-ary OR
12,581✔
191
    assert(n > 1);
192
    return mk_or(tm, n, children);
12,581✔
193
  case XOR_TERM:           // n-ary XOR
3✔
194
    return mk_xor(tm, n, children);
3✔
195
  case ARITH_EQ_ATOM:
45✔
196
    assert(n == 1);
197
    return mk_arith_eq(tm, children[0], zero_term);
45✔
198
  case ARITH_GE_ATOM:
374✔
199
    assert(n == 1);
200
    return mk_arith_geq(tm, children[0], zero_term);
374✔
201
  case ARITH_BINEQ_ATOM:   // equality: (t1 == t2)  (between two arithmetic terms)
203✔
202
    assert(n == 2);
203
    return mk_arith_eq(tm, children[0], children[1]);
203✔
204
  case APP_TERM:           // application of an uninterpreted function
771✔
205
    assert(n > 1);
206
    return mk_application(tm, children[0], n-1, children + 1);
771✔
207
  case ARITH_RDIV:
21✔
208
    assert(n == 2);
209
    return mk_arith_rdiv(tm, children[0], children[1]);
21✔
210
  case ARITH_IDIV:          // division: (div x y) as defined in SMT-LIB 2
14✔
211
    assert(n == 2);
212
    return mk_arith_idiv(tm, children[0], children[1]);
14✔
213
  case ARITH_MOD:          // remainder: (mod x y) is y - x * (div x y)
21✔
214
    assert(n == 2);
215
    return mk_arith_mod(tm, children[0], children[1]);
21✔
216
  case UPDATE_TERM:
492✔
217
    assert(n > 2);
218
    return mk_update(tm, children[0], n-2, children + 1, children[n-1]);
492✔
219
  case BV_ARRAY:
6,975✔
220
    assert(n >= 1);
221
    return mk_bvarray(tm, n, children);
6,975✔
222
  case BV_DIV:
63✔
223
    assert(n == 2);
224
    return mk_bvdiv(tm, children[0], children[1]);
63✔
225
  case BV_REM:
18✔
226
    assert(n == 2);
227
    return mk_bvrem(tm, children[0], children[1]);
18✔
228
  case BV_SDIV:
×
229
    assert(n == 2);
230
    return mk_bvsdiv(tm, children[0], children[1]);
×
231
  case BV_SREM:
×
232
    assert(n == 2);
233
    return mk_bvsrem(tm, children[0], children[1]);
×
234
  case BV_SMOD:
2✔
235
    assert(n == 2);
236
    return mk_bvsmod(tm, children[0], children[1]);
2✔
237
  case BV_SHL:
108✔
238
    assert(n == 2);
239
    return mk_bvshl(tm, children[0], children[1]);
108✔
240
  case BV_LSHR:
135✔
241
    assert(n == 2);
242
    return mk_bvlshr(tm, children[0], children[1]);
135✔
243
  case BV_ASHR:
3✔
244
    assert(n == 2);
245
    return mk_bvashr(tm, children[0], children[1]);
3✔
246
  case BV_EQ_ATOM:
6,549✔
247
    assert(n == 2);
248
    return mk_bveq(tm, children[0], children[1]);
6,549✔
249
  case BV_GE_ATOM:
1,797✔
250
    assert(n == 2);
251
    return mk_bvge(tm, children[0], children[1]);
1,797✔
252
  case BV_SGE_ATOM:
281✔
253
    assert(n == 2);
254
    return mk_bvsge(tm, children[0], children[1]);
281✔
255
  default:
×
256
    assert(false);
257
    return NULL_TERM;
×
258
  }
259
}
260

261
/**
262
 * Returns purified version of t if we should purify t as an argument of a function.
263
 * Any new equalities are added to output.
264
 */
265
static inline
266
term_t preprocessor_purify(preprocessor_t* pre, term_t t, ivector_t* out) {
53,562✔
267

268
  term_table_t* terms = pre->terms;
53,562✔
269

270
  // Negated terms must be purified
271
  if (is_pos_term(t)) {
53,562✔
272
    // We don't purify variables
273
    switch (term_kind(terms, t)) {
16,722✔
274
    case UNINTERPRETED_TERM:
10,802✔
275
      // Variables are already pure
276
      return t;
10,802✔
277
    case CONSTANT_TERM:
8✔
278
      return t;
8✔
279
    case ARITH_CONSTANT:
1,619✔
280
    case ARITH_FF_CONSTANT:
281
    case BV64_CONSTANT:
282
    case BV_CONSTANT:
283
      // Constants are also pure (except for false)
284
      return t;
1,619✔
285
    case APP_TERM:
1,595✔
286
      // Uninterpreted functions are also already purified
287
      return t;
1,595✔
288
    case UPDATE_TERM:
1,675✔
289
      return t;
1,675✔
290
    default:
1,023✔
291
      break;
1,023✔
292
    }
293
  }
294

295
  // Everything else gets purified. Check if in the cache
296
  int_hmap_pair_t* find = int_hmap_find(&pre->purification_map, t);
37,863✔
297
  if (find != NULL) {
37,863✔
298
    return find->val;
37,344✔
299
  } else {
300
    // Make the variable
301
    type_t t_type = term_type(terms, t);
519✔
302
    term_t x = new_uninterpreted_term(terms, t_type);
519✔
303
    // Remember for later
304
    int_hmap_add(&pre->purification_map, t, x);
519✔
305
    ivector_push(&pre->purification_map_list, t);
519✔
306
    // Also add the variable to the pre-processor
307
    preprocessor_set(pre, x, x);
519✔
308
    // Add equality to output
309
    term_t eq = mk_eq(&pre->tm, x, t);
519✔
310
    ivector_push(out, eq);
519✔
311

312
    if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
519✔
313
      mcsat_trace_printf(pre->tracer, "adding lemma = ");
×
314
      trace_term_ln(pre->tracer, terms, eq);
×
315
    }
316

317
    // Return the purified version
318
    return x;
519✔
319
  }
320
}
321

322
static inline
323
term_t mk_bvneg(term_manager_t* tm, term_t t) {
92✔
324
  term_table_t* terms = tm->terms;
92✔
325
  if (term_bitsize(terms,t) <= 64) {
92✔
326
    bvarith64_buffer_t *buffer = term_manager_get_bvarith64_buffer(tm);
76✔
327
    bvarith64_buffer_set_term(buffer, terms, t);
76✔
328
    bvarith64_buffer_negate(buffer);
76✔
329
    return mk_bvarith64_term(tm, buffer);
76✔
330
  } else {
331
    bvarith_buffer_t *buffer = term_manager_get_bvarith_buffer(tm);
16✔
332
    bvarith_buffer_set_term(buffer, terms, t);
16✔
333
    bvarith_buffer_negate(buffer);
16✔
334
    return mk_bvarith_term(tm, buffer);
16✔
335
  }
336
}
337

338
// Mark equality eq: (var = t) for solving
339
static
340
void preprocessor_mark_eq(preprocessor_t* pre, term_t eq, term_t var) {
24,851✔
341
  assert(is_pos_term(eq));
342
  assert(is_pos_term(var));
343
  assert(term_kind(pre->terms, var) == UNINTERPRETED_TERM);
344

345
  // Mark the equality
346
  int_hmap_pair_t* find = int_hmap_get(&pre->equalities, eq);
24,851✔
347
  assert(find->val == -1);
348
  find->val = var;
24,851✔
349
  ivector_push(&pre->equalities_list, eq);
24,851✔
350
}
24,851✔
351

352
static
353
term_t preprocessor_get_eq_solved_var(const preprocessor_t* pre, term_t eq) {
47,486✔
354
  assert(is_pos_term(eq));
355
  int_hmap_pair_t* find = int_hmap_find((int_hmap_t*) &pre->equalities, eq);
47,486✔
356
  if (find != NULL) {
47,486✔
357
    return find->val;
19,971✔
358
  } else {
359
    return NULL_TERM;
27,515✔
360
  }
361
}
362

363
term_t preprocessor_apply(preprocessor_t* pre, term_t t, ivector_t* out, bool is_assertion) {
39,497✔
364

365
  term_table_t* terms = pre->terms;
39,497✔
366
  term_manager_t* tm = &pre->tm;
39,497✔
367

368
  uint32_t i, j, n;
369

370
  // Check if already preprocessed;
371
  term_t t_pre = preprocessor_get(pre, t);
39,497✔
372
  if (t_pre != NULL_TERM) {
39,497✔
373
    return t_pre;
1,557✔
374
  }
375

376
// Note: negative affect on general performance due to solved/substituted
377
//       terms being to complex for explainers.
378
//
379
//  // First, if the assertion is a conjunction, just expand
380
//  if (is_assertion && is_neg_term(t) && term_kind(terms, t) == OR_TERM) {
381
//    // !(or t1 ... tn) -> !t1 && ... && !tn
382
//    composite_term_t* t_desc = composite_term_desc(terms, t);
383
//    for (i = 0; i < t_desc->arity; ++ i) {
384
//      ivector_push(out, opposite_term(t_desc->arg[i]));
385
//    }
386
//    return true_term;
387
//  }
388
//
389
  // Start
390
  ivector_t* pre_stack = &pre->preprocessing_stack;
37,940✔
391
  ivector_reset(pre_stack);
37,940✔
392
  ivector_push(pre_stack, t);
37,940✔
393

394
  // Preprocess
395
  while (pre_stack->size) {
509,642✔
396
    // Current term
397
    term_t current = ivector_last(pre_stack);
471,702✔
398

399
    if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
471,702✔
400
      mcsat_trace_printf(pre->tracer, "current = ");
×
401
      trace_term_ln(pre->tracer, terms, current);
×
402
    }
403

404
    // If preprocessed already, done
405
    term_t current_pre = preprocessor_get(pre, current);
471,702✔
406
    if (current_pre != NULL_TERM) {
471,702✔
407
      ivector_pop(pre_stack);
31,471✔
408
      continue;
31,471✔
409
    }
410

411
    // Negation
412
    if (is_neg_term(current)) {
440,231✔
413
      term_t child = unsigned_term(current);
89,928✔
414
      term_t child_pre = preprocessor_get(pre, child);
89,928✔
415
      if (child_pre == NULL_TERM) {
89,928✔
416
        ivector_push(pre_stack, child);
42,496✔
417
        continue;
42,496✔
418
      } else {
419
        ivector_pop(pre_stack);
47,432✔
420
        current_pre = opposite_term(child_pre);
47,432✔
421
        preprocessor_set(pre, current, current_pre);
47,432✔
422
        continue;
47,432✔
423
      }
424
    }
425

426
    // Check for supported types
427
    type_kind_t type = term_type_kind(terms, current);
350,303✔
428
    switch (type) {
350,303✔
429
    case BOOL_TYPE:
350,303✔
430
    case INT_TYPE:
431
    case REAL_TYPE:
432
    case FF_TYPE:
433
    case UNINTERPRETED_TYPE:
434
    case FUNCTION_TYPE:
435
    case BITVECTOR_TYPE:
436
    case SCALAR_TYPE:
437
      break;
350,303✔
438
    default:
×
439
      longjmp(*pre->exception, MCSAT_EXCEPTION_UNSUPPORTED_THEORY);
×
440
    }
441

442
    // Kind of term
443
    term_kind_t current_kind = term_kind(terms, current);
350,303✔
444

445
    switch(current_kind) {
350,303✔
446
    case CONSTANT_TERM:    // constant of uninterpreted/scalar/boolean types
1,757✔
447
    case BV64_CONSTANT:    // compact bitvector constant (64 bits at most)
448
    case BV_CONSTANT:      // generic bitvector constant (more than 64 bits)
449
    case ARITH_CONSTANT:   // rational constant
450
    case ARITH_FF_CONSTANT:   // finite field constant
451
      current_pre = current;
1,757✔
452
      break;
1,757✔
453

454
    case UNINTERPRETED_TERM:  // (i.e., global variables, can't be bound).
14,617✔
455
      current_pre = current;
14,617✔
456
      // Unless we want special slicing
457
      if (type == BITVECTOR_TYPE) {
14,617✔
458
        if (pre->options->bv_var_size > 0) {
5,016✔
459
          uint32_t size = term_bitsize(terms, current);
23✔
460
          uint32_t var_size = pre->options->bv_var_size;
23✔
461
          if (size > var_size) {
23✔
462
            uint32_t n_vars = (size - 1) / var_size + 1;
2✔
463
            term_t vars[n_vars];
2✔
464
            for (i = n_vars - 1; size > 0; i--) {
8✔
465
              if (size >= var_size) {
6✔
466
                vars[i] = new_uninterpreted_term(terms, bv_type(terms->types, var_size));
4✔
467
                size -= var_size;
4✔
468
              } else {
469
                vars[i] = new_uninterpreted_term(terms, bv_type(terms->types, size));
2✔
470
                size = 0;
2✔
471
              }
472
            }
473
            current_pre = _o_yices_bvconcat(n_vars, vars);
2✔
474
            term_t eq = _o_yices_eq(current, current_pre);
2✔
475
            preprocessor_mark_eq(pre, eq, current);
2✔
476
          }
477
        }
478
      }
479
      break;
14,617✔
480

481
    case ITE_TERM:           // if-then-else
183,599✔
482
    case ITE_SPECIAL:        // special if-then-else term (NEW: EXPERIMENTAL)
483
    case EQ_TERM:            // equality
484
    case OR_TERM:            // n-ary OR
485
    case XOR_TERM:           // n-ary XOR
486
    case ARITH_EQ_ATOM:      // equality (t == 0)
487
    case ARITH_BINEQ_ATOM:   // equality (t1 == t2)  (between two arithmetic terms)
488
    case ARITH_GE_ATOM:      // inequality (t >= 0)
489
    case ARITH_FF_EQ_ATOM:   // finite field equality (t == 0)
490
    case ARITH_FF_BINEQ_ATOM: // finite field equality (t1 == t2)  (between two arithmetic terms)
491
    case BV_DIV:
492
    case BV_REM:
493
    case BV_SMOD:
494
    case BV_SHL:
495
    case BV_LSHR:
496
    case BV_ASHR:
497
    case BV_EQ_ATOM:
498
    case BV_GE_ATOM:
499
    case BV_SGE_ATOM:
500
    {
501
      composite_term_t* desc = get_composite(terms, current_kind, current);
183,599✔
502
      bool children_done = true;
183,599✔
503
      bool children_same = true;
183,599✔
504

505
      n = desc->arity;
183,599✔
506

507
      /*
508
      // Arrays not supported yet
509
      if (current_kind == EQ_TERM && term_type_kind(terms, desc->arg[0]) == FUNCTION_TYPE) {
510
        longjmp(*pre->exception, MCSAT_EXCEPTION_UNSUPPORTED_THEORY);
511
      }
512
      */
513
 
514
      // Is this a top-level equality assertion
515
      bool is_equality =
183,599✔
516
          current_kind == EQ_TERM ||
162,953✔
517
          current_kind == BV_EQ_ATOM ||
104,455✔
518
          current_kind == ARITH_EQ_ATOM ||
100,827✔
519
          current_kind == ARITH_BINEQ_ATOM ||
96,902✔
520
          current_kind == ARITH_FF_EQ_ATOM ||
346,552✔
521
          current_kind == ARITH_FF_BINEQ_ATOM;
522
      // don't rewrite if the equality is between Boolean terms
523
      bool is_boolean = is_boolean_type(term_type(pre->terms, desc->arg[0]));
183,599✔
524

525
      term_t eq_solve_var = NULL_TERM;
183,599✔
526
      if (is_assertion && is_equality && !is_boolean) {
183,599✔
527
        bool is_lhs_rhs_mixed = desc->arity > 1 &&
141,819✔
528
          term_type_kind(pre->terms, desc->arg[0]) != term_type_kind(pre->terms, desc->arg[1]);
69,018✔
529
        // don't rewrite if equality is between mixed terms, e.g. between int and real terms
530
        if (!is_lhs_rhs_mixed && current == t) {
72,801✔
531
          eq_solve_var = preprocessor_get_eq_solved_var(pre, t);
47,484✔
532
          if (eq_solve_var == NULL_TERM) {
47,484✔
533
            term_t lhs = desc->arg[0];
27,515✔
534
            term_kind_t lhs_kind = term_kind(terms, lhs);
27,515✔
535
            // If lhs/rhs is a first-time seen variable, we can solve it
536
            bool lhs_is_var = lhs_kind == UNINTERPRETED_TERM && is_pos_term(lhs);
27,515✔
537
            if (lhs_is_var && preprocessor_get(pre, lhs) == NULL_TERM) {
27,515✔
538
              // First time variable, let's solve
539
              preprocessor_mark_eq(pre, t, lhs);
24,594✔
540
              eq_solve_var = lhs;
24,594✔
541
            } else if (desc->arity > 1) {
2,921✔
542
              term_t rhs = desc->arg[1];
2,219✔
543
              term_kind_t rhs_kind = term_kind(terms, rhs);
2,219✔
544
              bool rhs_is_var = rhs_kind == UNINTERPRETED_TERM && is_pos_term(rhs);
2,219✔
545
              if (rhs_is_var && preprocessor_get(pre, rhs) == NULL_TERM) {
2,219✔
546
                // First time variable, let's solve
547
                preprocessor_mark_eq(pre, t, rhs);
255✔
548
                eq_solve_var = rhs;
255✔
549
              }
550
            }
551
          } else {
552
            // Check that we it's not there already
553
            if (preprocessor_get(pre, eq_solve_var) != NULL_TERM) {
19,969✔
554
              eq_solve_var = NULL_TERM;
61✔
555
            }
556
          }
557
        }
558
      }
559

560
      ivector_t children;
561
      init_ivector(&children, n);
183,599✔
562

563
      for (i = 0; i < n; ++ i) {
611,671✔
564
        term_t child = desc->arg[i];
428,072✔
565
        if (child != eq_solve_var) {
428,072✔
566
          term_t child_pre = preprocessor_get(pre, child);
383,315✔
567
          if (child_pre == NULL_TERM) {
383,315✔
568
            children_done = false;
110,346✔
569
            ivector_push(pre_stack, child);
110,346✔
570
          } else if (child_pre != child) {
272,969✔
571
            children_same = false;
106,144✔
572
          }
573
          if (children_done) {
383,315✔
574
            ivector_push(&children, child_pre);
259,029✔
575
          }
576
        }
577
      }
578

579
      if (eq_solve_var != NULL_TERM) {
183,599✔
580
        // Check again to make sure we don't have something like x = x + 1
581
        if (preprocessor_get(pre, eq_solve_var) != NULL_TERM) {
44,757✔
582
          // Do it again
583
          children_done = false;
×
584
        }
585
      }
586

587
      if (children_done) {
183,599✔
588
        if (eq_solve_var != NULL_TERM) {
114,604✔
589
          term_t eq_solve_term = zero_term;
24,788✔
590
          if (children.size > 0) {
24,788✔
591
            eq_solve_term = children.data[0];
24,750✔
592
          }
593
          preprocessor_set(pre, eq_solve_var, eq_solve_term);
24,788✔
594
          current_pre = true_term;
24,788✔
595
        } else {
596
          if (children_same) {
89,816✔
597
            current_pre = current;
51,338✔
598
          } else {
599
            current_pre = mk_composite(pre, current_kind, n, children.data);
38,478✔
600
          }
601
        }
602
      }
603

604
      delete_ivector(&children);
183,599✔
605

606
      break;
183,599✔
607
    }
608

609
    case BV_ARRAY:
17,561✔
610
    {
611
      composite_term_t* desc = get_composite(terms, current_kind, current);
17,561✔
612
      bool children_done = true;
17,561✔
613
      bool children_same = true;
17,561✔
614

615
      n = desc->arity;
17,561✔
616

617
      ivector_t children;
618
      init_ivector(&children, n);
17,561✔
619

620
      for (i = 0; i < n; ++ i) {
355,722✔
621
        term_t child = desc->arg[i];
338,161✔
622
        term_t child_pre = preprocessor_get(pre, child);
338,161✔
623
        if (child_pre == NULL_TERM) {
338,161✔
624
          children_done = false;
143,656✔
625
          ivector_push(pre_stack, child);
143,656✔
626
        } else {
627
          if (is_arithmetic_literal(terms, child_pre) || child_pre == false_term) {
194,505✔
628
            // purify if arithmetic literal, i.e. a = 0 where a is of integer type
629
            child_pre = preprocessor_purify(pre, child_pre, out);
36,819✔
630
          }
631
          if (child_pre != child) {
194,505✔
632
            children_same = false;
111,137✔
633
          }
634
        }
635
        if (children_done) {
338,161✔
636
          ivector_push(&children, child_pre);
180,883✔
637
        }
638
      }
639

640
      if (children_done) {
17,561✔
641
        if (children_same) {
9,189✔
642
          current_pre = current;
2,214✔
643
        } else {
644
          current_pre = mk_composite(pre, current_kind, n, children.data);
6,975✔
645
        }
646
      }
647

648
      delete_ivector(&children);
17,561✔
649

650
      break;
17,561✔
651
    }
652

653
    case ARITH_ABS:
4✔
654
    {
655
      term_t arg = arith_abs_arg(terms, current);
4✔
656
      term_t arg_pre = preprocessor_get(pre, arg);
4✔
657
      if (arg_pre == NULL_TERM) {
4✔
658
        ivector_push(pre_stack, arg);
1✔
659
      } else {
660
        type_t arg_pre_type = term_type(pre->terms, arg_pre);
3✔
661
        term_t arg_pre_is_positive = mk_arith_term_geq0(&pre->tm, arg_pre);
3✔
662
        term_t arg_negative = _o_yices_neg(arg_pre);
3✔
663
        current_pre = mk_ite(&pre->tm, arg_pre_is_positive, arg_pre, arg_negative, arg_pre_type);
3✔
664
      }
665
      break;
4✔
666
    }
667

668
    case BV_SDIV:
20✔
669
    {
670
      composite_term_t* desc = get_composite(terms, current_kind, current);
20✔
671
      assert(desc->arity == 2);
672
      term_t s = desc->arg[0];
20✔
673
      term_t s_pre = preprocessor_get(pre, s);
20✔
674
      if (s_pre == NULL_TERM) {
20✔
675
        ivector_push(pre_stack, s);
7✔
676
      }
677
      term_t t = desc->arg[1];
20✔
678
      term_t t_pre = preprocessor_get(pre, t);
20✔
679
      if (t_pre == NULL_TERM) {
20✔
680
        ivector_push(pre_stack, t);
5✔
681
      }
682
      if (s_pre != NULL_TERM && t_pre != NULL_TERM) {
20✔
683
        type_t tau = term_type(terms, s_pre);
11✔
684
        uint32_t n = term_bitsize(terms, s_pre);
11✔
685
        term_t msb_s = mk_bitextract(tm, s_pre, n-1);
11✔
686
        term_t msb_t = mk_bitextract(tm, t_pre, n-1);
11✔
687
        // if (msb_s) {
688
        //   if (msb_t) {
689
        //     t1: udiv(-s, -t)
690
        //   } else {
691
        //     t2: -udiv(-s, t)
692
        //   }
693
        // } else {
694
        //   if (msb_t) {
695
        //     t3: -udiv(s, -t)
696
        //   } else {
697
        //     t4: udiv(s, t)
698
        //   }
699
        // }
700
        term_t neg_s = mk_bvneg(tm, s_pre);
11✔
701
        term_t neg_t = mk_bvneg(tm, t_pre);
11✔
702

703
        term_t t1 = mk_bvdiv(tm, neg_s, neg_t);
11✔
704
        term_t t2 = mk_bvdiv(tm, neg_s, t_pre);
11✔
705
        t2 = mk_bvneg(&pre->tm, t2);
11✔
706
        term_t t3 = mk_bvdiv(tm, s_pre, neg_t);
11✔
707
        t3 = mk_bvneg(&pre->tm, t3);
11✔
708
        term_t t4 = mk_bvdiv(tm, s_pre, t_pre);
11✔
709

710
        term_t b1 = mk_ite(tm, msb_t, t1, t2, tau);
11✔
711
        term_t b2 = mk_ite(tm, msb_t, t3, t4, tau);
11✔
712

713
        current_pre = mk_ite(tm, msb_s, b1, b2, tau);
11✔
714
      }
715
      break;
20✔
716
    }
717
    case BV_SREM:
21✔
718
    {
719
      composite_term_t* desc = get_composite(terms, current_kind, current);
21✔
720
      assert(desc->arity == 2);
721
      term_t s = desc->arg[0];
21✔
722
      term_t s_pre = preprocessor_get(pre, s);
21✔
723
      if (s_pre == NULL_TERM) {
21✔
724
        ivector_push(pre_stack, s);
8✔
725
      }
726
      term_t t = desc->arg[1];
21✔
727
      term_t t_pre = preprocessor_get(pre, t);
21✔
728
      if (t_pre == NULL_TERM) {
21✔
729
        ivector_push(pre_stack, t);
3✔
730
      }
731
      if (s_pre != NULL_TERM && t_pre != NULL_TERM) {
21✔
732
        type_t tau = term_type(terms, s_pre);
12✔
733
        uint32_t n = term_bitsize(terms, s_pre);
12✔
734
        term_t msb_s = mk_bitextract(tm, s_pre, n-1);
12✔
735
        term_t msb_t = mk_bitextract(tm, t_pre, n-1);
12✔
736
        // if (msb_s) {
737
        //   if (msb_t) {
738
        //     t1: -urem(-s, -t)
739
        //   } else {
740
        //     t2: -urem(-s, t)
741
        //   }
742
        // } else {
743
        //   if (msb_t) {
744
        //     t3: -urem(s, -t)
745
        //   } else {
746
        //     t4: urem(s, t)
747
        //   }
748
        // }
749
        term_t neg_s = mk_bvneg(tm, s_pre);
12✔
750
        term_t neg_t = mk_bvneg(tm, t_pre);
12✔
751

752
        term_t t1 = mk_bvrem(tm, neg_s, neg_t);
12✔
753
        t1 = mk_bvneg(tm, t1);
12✔
754
        term_t t2 = mk_bvrem(tm, neg_s, t_pre);
12✔
755
        t2 = mk_bvneg(tm, t2);
12✔
756
        term_t t3 = mk_bvrem(tm, s_pre, neg_t);
12✔
757
        term_t t4 = mk_bvrem(tm, s_pre, t_pre);
12✔
758

759
        term_t b1 = mk_ite(tm, msb_t, t1, t2, tau);
12✔
760
        term_t b2 = mk_ite(tm, msb_t, t3, t4, tau);
12✔
761

762
        current_pre = mk_ite(tm, msb_s, b1, b2, tau);
12✔
763
      }
764
      break;
21✔
765
    }
766
    case BIT_TERM: // bit-select current = child[i]
112,996✔
767
    {
768
      uint32_t index = bit_term_index(terms, current);
112,996✔
769
      term_t arg = bit_term_arg(terms, current);
112,996✔
770
      term_t arg_pre = preprocessor_get(pre, arg);
112,996✔
771
      if (arg_pre == NULL_TERM) {
112,996✔
772
        ivector_push(pre_stack, arg);
1,587✔
773
      } else {
774
        if (arg_pre == arg) {
111,409✔
775
          current_pre = current;
73,367✔
776
        } else {
777
          if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
38,042✔
778
            mcsat_trace_printf(pre->tracer, "arg_pre = ");
×
779
            trace_term_ln(pre->tracer, terms, arg_pre);
×
780
          }
781
          // For simplification purposes use API
782
          current_pre = _o_yices_bitextract(arg_pre, index);
38,042✔
783
          assert(current_pre != NULL_TERM);
784
        }
785
      }
786
      break;
112,996✔
787
    }
788
    case BV_POLY:  // polynomial with generic bitvector coefficients
33✔
789
    {
790
      bvpoly_t* p = bvpoly_term_desc(terms, current);
33✔
791

792
      bool children_done = true;
33✔
793
      bool children_same = true;
33✔
794

795
      n = p->nterms;
33✔
796

797
      ivector_t children;
798
      init_ivector(&children, n);
33✔
799

800
      for (i = 0; i < n; ++ i) {
84✔
801
        term_t x = p->mono[i].var;
51✔
802
        term_t x_pre = (x == const_idx ? const_idx : preprocessor_get(pre, x));
51✔
803

804
        if (x_pre != const_idx) {
51✔
805
          if (x_pre == NULL_TERM) {
47✔
806
            children_done = false;
10✔
807
            ivector_push(pre_stack, x);
10✔
808
          } else if (x_pre != x) {
37✔
809
            children_same = false;
23✔
810
          }
811
        }
812

813
        if (children_done) { ivector_push(&children, x_pre); }
51✔
814
      }
815

816
      if (children_done) {
33✔
817
        if (children_same) {
26✔
818
          current_pre = current;
11✔
819
        } else {
820
          current_pre = mk_bvarith_poly(tm, p, n, children.data);
15✔
821
        }
822
      }
823

824
      delete_ivector(&children);
33✔
825

826
      break;
33✔
827
    }
828
    case BV64_POLY: // polynomial with 64bit coefficients
2,804✔
829
    {
830
      bvpoly64_t* p = bvpoly64_term_desc(terms, current);
2,804✔
831

832
      bool children_done = true;
2,804✔
833
      bool children_same = true;
2,804✔
834

835
      n = p->nterms;
2,804✔
836

837
      ivector_t children;
838
      init_ivector(&children, n);
2,804✔
839

840
      for (i = 0; i < n; ++ i) {
10,520✔
841
        term_t x = p->mono[i].var;
7,716✔
842
        term_t x_pre = (x == const_idx ? const_idx : preprocessor_get(pre, x));
7,716✔
843

844
        if (x_pre != const_idx) {
7,716✔
845
          if (x_pre == NULL_TERM) {
5,839✔
846
            children_done = false;
1,394✔
847
            ivector_push(pre_stack, x);
1,394✔
848
          } else if (x_pre != x) {
4,445✔
849
            children_same = false;
3,567✔
850
          }
851
        }
852

853
        if (children_done) { ivector_push(&children, x_pre); }
7,716✔
854
      }
855

856
      if (children_done) {
2,804✔
857
        if (children_same) {
2,027✔
858
          current_pre = current;
435✔
859
        } else {
860
          current_pre = mk_bvarith64_poly(tm, p, n, children.data);
1,592✔
861
        }
862
      }
863

864
      delete_ivector(&children);
2,804✔
865

866
      break;
2,804✔
867
    }
868

869
    case POWER_PRODUCT:    // power products: (t1^d1 * ... * t_n^d_n)
1,570✔
870
    {
871
      pprod_t* pp = pprod_term_desc(terms, current);
1,570✔
872
      bool children_done = true;
1,570✔
873
      bool children_same = true;
1,570✔
874

875
      n = pp->len;
1,570✔
876

877
      ivector_t children;
878
      init_ivector(&children, n);
1,570✔
879

880
      for (i = 0; i < n; ++ i) {
5,032✔
881
        term_t x = pp->prod[i].var;
3,462✔
882
        term_t x_pre = preprocessor_get(pre, x);
3,462✔
883

884
        if (x_pre == NULL_TERM) {
3,462✔
885
          children_done = false;
409✔
886
          ivector_push(pre_stack, x);
409✔
887
        } else if (x_pre != x) {
3,053✔
888
          children_same = false;
86✔
889
        }
890

891
        if (children_done) { ivector_push(&children, x_pre); }
3,462✔
892
      }
893

894
      if (children_done) {
1,570✔
895
        if (children_same) {
1,268✔
896
          current_pre = current;
1,218✔
897
        } else {
898
          // NOTE: it doens't change pp, it just uses it as a frame
899
          current_pre = mk_pprod(tm, pp, n, children.data);
50✔
900
        }
901
      }
902

903
      delete_ivector(&children);
1,570✔
904

905
      break;
1,570✔
906
    }
907

908
    case ARITH_POLY:       // polynomial with rational coefficients
6,613✔
909
    {
910
      polynomial_t* p = poly_term_desc(terms, current);
6,613✔
911

912
      bool children_done = true;
6,613✔
913
      bool children_same = true;
6,613✔
914

915
      n = p->nterms;
6,613✔
916

917
      ivector_t children;
918
      init_ivector(&children, n);
6,613✔
919

920
      for (i = 0; i < n; ++ i) {
25,704✔
921
        term_t x = p->mono[i].var;
19,091✔
922
        term_t x_pre = (x == const_idx ? const_idx : preprocessor_get(pre, x));
19,091✔
923

924
        if (x_pre != const_idx) {
19,091✔
925
          if (x_pre == NULL_TERM) {
16,163✔
926
            children_done = false;
2,415✔
927
            ivector_push(pre_stack, x);
2,415✔
928
          } else if (x_pre != x) {
13,748✔
929
            children_same = false;
755✔
930
          }
931
        }
932

933
        if (children_done) { ivector_push(&children, x_pre); }
19,091✔
934
      }
935

936
      if (children_done) {
6,613✔
937
        if (children_same) {
5,261✔
938
          current_pre = current;
4,748✔
939
        } else {
940
          current_pre = mk_arith_poly(tm, p, n, children.data);
513✔
941
        }
942
      }
943

944
      delete_ivector(&children);
6,613✔
945

946
      break;
6,613✔
947
    }
948

949
    case ARITH_FF_POLY:    // polynomial with finite field coefficients
150✔
950
    {
951
      polynomial_t* p = finitefield_poly_term_desc(terms, current);
150✔
952
      const rational_t *mod = finitefield_term_order(terms, current);
150✔
953

954
      bool children_done = true;
150✔
955
      bool children_same = true;
150✔
956

957
      n = p->nterms;
150✔
958

959
      ivector_t children;
960
      init_ivector(&children, n);
150✔
961

962
      for (i = 0; i < n; ++ i) {
1,068✔
963
        term_t x = p->mono[i].var;
918✔
964
        term_t x_pre = (x == const_idx ? const_idx : preprocessor_get(pre, x));
918✔
965

966
        if (x_pre != const_idx) {
918✔
967
          if (x_pre == NULL_TERM) {
864✔
968
            children_done = false;
380✔
969
            ivector_push(pre_stack, x);
380✔
970
          } else if (x_pre != x) {
484✔
971
            children_same = false;
×
972
          }
973
        }
974

975
        if (children_done) { ivector_push(&children, x_pre); }
918✔
976
      }
977

978
      if (children_done) {
150✔
979
        if (children_same) {
75✔
980
          current_pre = current;
75✔
981
        } else {
982
          current_pre = mk_arith_ff_poly(tm, p, n, children.data, mod);
×
983
        }
984
      }
985

986
      delete_ivector(&children);
150✔
987

988
      break;
150✔
989
    }
990

991
    // FOLLOWING ARE UNINTEPRETED, SO WE PURIFY THE ARGUMENTS
992

993
    case APP_TERM:           // application of an uninterpreted function
8,527✔
994
    case ARITH_RDIV:         // regular division (/ x y)
995
    case ARITH_IDIV:         // division: (div x y) as defined in SMT-LIB 2
996
    case ARITH_MOD:          // remainder: (mod x y) is y - x * (div x y)
997
    case UPDATE_TERM:        // update array
998
    {
999
      composite_term_t* desc = get_composite(terms, current_kind, current);
8,527✔
1000
      bool children_done = true;
8,527✔
1001
      bool children_same = true;
8,527✔
1002

1003
      n = desc->arity;
8,527✔
1004

1005
      ivector_t children;
1006
      init_ivector(&children, n);
8,527✔
1007

1008
      for (i = 0; i < n; ++ i) {
29,291✔
1009
        term_t child = desc->arg[i];
20,764✔
1010
        term_t child_pre = preprocessor_get(pre, child);
20,764✔
1011

1012
        if (child_pre == NULL_TERM) {
20,764✔
1013
          children_done = false;
4,024✔
1014
          ivector_push(pre_stack, child);
4,024✔
1015
        } else {
1016
          // Purify if needed
1017
          child_pre = preprocessor_purify(pre, child_pre, out);
16,740✔
1018
          // If interpreted terms, we need to purify non-variables
1019
          if (child_pre != child) { children_same = false; }
16,740✔
1020
        }
1021

1022
        if (children_done) { ivector_push(&children, child_pre); }
20,764✔
1023
      }
1024

1025
      if (children_done) {
8,527✔
1026
        if (children_same) {
5,545✔
1027
          current_pre = current;
4,226✔
1028
        } else {
1029
          current_pre = mk_composite(pre, current_kind, n, children.data);
1,319✔
1030
        }
1031
      }
1032

1033
      delete_ivector(&children);
8,527✔
1034

1035
      break;
8,527✔
1036
    }
1037

1038
    case ARITH_IS_INT_ATOM:
×
1039
    {
1040
      // replace with t <= floor(t)
1041
      term_t child = arith_is_int_arg(terms, current);
×
1042
      term_t child_pre = preprocessor_get(pre, child);
×
1043
      if (child_pre != NULL_TERM) {
×
1044
        child_pre = preprocessor_purify(pre, child_pre, out);
×
1045
        current_pre = arith_floor(terms, child_pre);
×
1046
        current_pre = mk_arith_leq(tm, child_pre, current_pre);
×
1047
      } else {
1048
        ivector_push(pre_stack, child);
×
1049
      }
1050
      break;
×
1051
    }
1052

1053
    case ARITH_FLOOR:        // floor: purify, but its interpreted
7✔
1054
    {
1055
      term_t child = arith_floor_arg(terms, current);
7✔
1056
      term_t child_pre = preprocessor_get(pre, child);
7✔
1057

1058
      if (child_pre != NULL_TERM) {
7✔
1059
        if (term_kind(terms, child_pre) == ARITH_CONSTANT) {
4✔
1060
          rational_t floor;
1061
          q_init(&floor);
1✔
1062
          q_set(&floor, rational_term_desc(terms, child_pre));
1✔
1063
          q_floor(&floor);
1✔
1064
          current_pre = arith_constant(terms, &floor);
1✔
1065
          q_clear(&floor);
1✔
1066
        } else {
1067
          child_pre = preprocessor_purify(pre, child_pre, out);
3✔
1068
          if (child_pre != child) {
3✔
1069
            current_pre = arith_floor(terms, child_pre);
1✔
1070
          } else {
1071
            current_pre = current;
2✔
1072
          }
1073
        }
1074
      } else {
1075
        ivector_push(pre_stack, child);
3✔
1076
      }
1077

1078
      break;
7✔
1079
    }
1080

1081
    case ARITH_CEIL:        // floor: purify, but its interpreted
×
1082
    {
1083
      term_t child = arith_ceil_arg(terms, current);
×
1084
      term_t child_pre = preprocessor_get(pre, child);
×
1085

1086
      if (child_pre != NULL_TERM) {
×
1087
        child_pre = preprocessor_purify(pre, child_pre, out);
×
1088
        if (child_pre != child) {
×
1089
          current_pre = arith_floor(terms, child_pre);
×
1090
        } else {
1091
          current_pre = current;
×
1092
        }
1093
      } else {
1094
        ivector_push(pre_stack, child);
×
1095
      }
1096

1097
      break;
×
1098
    }
1099

1100
    case DISTINCT_TERM:
24✔
1101
    {
1102
      composite_term_t* desc = get_composite(terms, current_kind, current);
24✔
1103

1104
      bool children_done = true;
24✔
1105
      n = desc->arity;
24✔
1106

1107
      ivector_t children;
1108
      init_ivector(&children, n);
24✔
1109

1110
      for (i = 0; i < n; ++ i) {
122✔
1111
        term_t child = desc->arg[i];
98✔
1112
        term_t child_pre = preprocessor_get(pre, child);
98✔
1113

1114
        if (child_pre == NULL_TERM) {
98✔
1115
          children_done = false;
41✔
1116
          ivector_push(pre_stack, child);
41✔
1117
        }
1118

1119
        if (children_done) { ivector_push(&children, child_pre); }
98✔
1120
      }
1121

1122
      if (children_done) {
24✔
1123
        ivector_t distinct;
1124
        init_ivector(&distinct, 0);
14✔
1125

1126
        for (i = 0; i < n; ++ i) {
70✔
1127
          for (j = i + 1; j < n; ++ j) {
148✔
1128
            term_t neq = mk_eq(&pre->tm, children.data[i], children.data[j]);
92✔
1129
            neq = opposite_term(neq);
92✔
1130
            ivector_push(&distinct, neq);
92✔
1131
          }
1132
        }
1133
        current_pre = mk_and(&pre->tm, distinct.size, distinct.data);
14✔
1134

1135
        delete_ivector(&distinct);
14✔
1136
      }
1137

1138
      delete_ivector(&children);
24✔
1139

1140
      break;
24✔
1141
    }
1142

1143
    default:
×
1144
      // UNSUPPORTED TERM/THEORY
1145
      longjmp(*pre->exception, MCSAT_EXCEPTION_UNSUPPORTED_THEORY);
×
1146
      break;
1147
    }
1148

1149
    if (current_pre != NULL_TERM) {
350,303✔
1150
      preprocessor_set(pre, current, current_pre);
265,822✔
1151
      ivector_pop(pre_stack);
265,822✔
1152
      if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
265,822✔
1153
        mcsat_trace_printf(pre->tracer, "current_pre = ");
×
1154
        trace_term_ln(pre->tracer, terms, current_pre);
×
1155
      }
1156
    }
1157

1158
  }
1159

1160
  // Return the result
1161
  t_pre = preprocessor_get(pre, t);
37,940✔
1162
  if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
37,940✔
1163
    mcsat_trace_printf(pre->tracer, "t_pre = ");
×
1164
    trace_term_ln(pre->tracer, terms, t_pre);
×
1165
  }
1166

1167
  ivector_reset(pre_stack);
37,940✔
1168

1169
  assert(t_pre != NULL_TERM);
1170
  return t_pre;
37,940✔
1171
}
1172

1173
void preprocessor_set_exception_handler(preprocessor_t* pre, jmp_buf* handler) {
×
1174
  pre->exception = handler;
×
1175
}
×
1176

1177
void preprocessor_push(preprocessor_t* pre) {
517✔
1178
  scope_holder_push(&pre->scope,
517✔
1179
      &pre->preprocess_map_list.size,
1180
      &pre->purification_map_list.size,
1181
      &pre->equalities_list.size,
1182
      NULL);
1183
}
517✔
1184

1185
void preprocessor_pop(preprocessor_t* pre) {
443✔
1186

1187
  uint32_t preprocess_map_list_size = 0;
443✔
1188
  uint32_t purification_map_list_size = 0;
443✔
1189
  uint32_t equalities_list_size = 0;
443✔
1190

1191
  scope_holder_pop(&pre->scope,
443✔
1192
      &preprocess_map_list_size,
1193
      &purification_map_list_size,
1194
      &equalities_list_size,
1195
      NULL);
1196

1197
  while (pre->preprocess_map_list.size > preprocess_map_list_size) {
13,605✔
1198
    term_t t = ivector_last(&pre->preprocess_map_list);
13,162✔
1199
    ivector_pop(&pre->preprocess_map_list);
13,162✔
1200
    int_hmap_pair_t* find = int_hmap_find(&pre->preprocess_map, t);
13,162✔
1201
    assert(find != NULL);
1202
    int_hmap_erase(&pre->preprocess_map, find);
13,162✔
1203
  }
1204

1205
  while (pre->purification_map_list.size > purification_map_list_size) {
579✔
1206
    term_t t = ivector_last(&pre->purification_map_list);
136✔
1207
    ivector_pop(&pre->purification_map_list);
136✔
1208
    int_hmap_pair_t* find = int_hmap_find(&pre->purification_map, t);
136✔
1209
    assert(find != NULL);
1210
    int_hmap_erase(&pre->purification_map, find);
136✔
1211
  }
1212

1213
  while (pre->equalities_list.size > equalities_list_size) {
493✔
1214
    term_t eq = ivector_last(&pre->equalities_list);
50✔
1215
    ivector_pop(&pre->equalities_list);
50✔
1216
    int_hmap_pair_t* find = int_hmap_find(&pre->equalities, eq);
50✔
1217
    assert(find != NULL);
1218
    int_hmap_erase(&pre->equalities, find);
50✔
1219
  }
1220
}
443✔
1221

1222
void preprocessor_build_model(preprocessor_t* pre, model_t* model) {
23✔
1223
  uint32_t i = 0;
23✔
1224
  for (i = 0; i < pre->equalities_list.size; ++ i) {
25✔
1225
    term_t eq = pre->equalities_list.data[i];
2✔
1226
    term_t eq_var = preprocessor_get_eq_solved_var(pre, eq);
2✔
1227
    if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
2✔
1228
      mcsat_trace_printf(pre->tracer, "eq = ");
×
1229
      trace_term_ln(pre->tracer, pre->terms, eq);
×
1230
      mcsat_trace_printf(pre->tracer, "\neq_var = ");
×
1231
      trace_term_ln(pre->tracer, pre->terms, eq_var);
×
1232
      mcsat_trace_printf(pre->tracer, "\n");
×
1233
    }
1234
    // Some equalities are solved, but then reasserted in the solver
1235
    // these already have a model
1236
    if (model_find_term_value(model, eq_var) != null_value) {
2✔
1237
      continue;
×
1238
    }
1239
    // Some equalities are marked, but not solved. These we skip as they
1240
    // are already set in the model
1241
    if (preprocessor_get(pre, eq_var) == eq_var) {
2✔
1242
      continue;
×
1243
    }
1244
    term_kind_t eq_kind = term_kind(pre->terms, eq);
2✔
1245
    composite_term_t* eq_desc = get_composite(pre->terms, eq_kind, eq);
2✔
1246
    if (eq_desc->arity > 1) {
2✔
1247
      term_t eq_subst = eq_desc->arg[0] == eq_var ? eq_desc->arg[1] : eq_desc->arg[0];
×
1248
      model_add_substitution(model, eq_var, eq_subst);
×
1249
    } else {
1250
      model_add_substitution(model, eq_var, zero_term);
2✔
1251
    }
1252
  }
1253
}
23✔
1254

1255

1256
static inline
1257
void preprocessor_gc_mark_term(preprocessor_t* pre, term_t t) {
1,260✔
1258
  term_table_set_gc_mark(pre->terms, index_of(t));
1,260✔
1259
  type_table_set_gc_mark(pre->terms->types, term_type(pre->terms, t));
1,260✔
1260
}
1,260✔
1261

1262
void preprocessor_gc_mark(preprocessor_t* pre) {
6✔
1263
  uint32_t i;
1264

1265
  for (i = 0; i < pre->preprocess_map_list.size; ++ i) {
612✔
1266
    term_t t = pre->preprocess_map_list.data[i];
606✔
1267
    preprocessor_gc_mark_term(pre, t);
606✔
1268
    term_t t_pre = preprocessor_get(pre, t);
606✔
1269
    preprocessor_gc_mark_term(pre, t_pre);
606✔
1270
  }
1271

1272
  for (i = 0; i < pre->equalities_list.size; ++ i) {
16✔
1273
    term_t t = pre->equalities_list.data[i];
10✔
1274
    preprocessor_gc_mark_term(pre, t);
10✔
1275
  }
1276

1277
  for (i = 0; i < pre->purification_map_list.size; ++ i) {
25✔
1278
    term_t t = pre->purification_map_list.data[i];
19✔
1279
    preprocessor_gc_mark_term(pre, t);
19✔
1280
    term_t t_pure = int_hmap_find(&pre->purification_map, t)->val;
19✔
1281
    preprocessor_gc_mark_term(pre, t_pure);
19✔
1282
  }
1283
}
6✔
1284

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc