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

SRI-CSL / yices2 / 12367760548

17 Dec 2024 06:41AM UTC coverage: 65.285% (-0.6%) from 65.92%
12367760548

push

github

web-flow
Fixes GitHub coverage issue (#544)

* Update action.yml

* Update action.yml

81020 of 124102 relevant lines covered (65.29%)

1509382.01 hits per line

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

57.43
/src/terms/balanced_arith_buffers.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
/*
20
 * BUFFER FOR ARITHMETIC OPERATIONS USING RED-BLACK TREES
21
 */
22

23
#include "terms/balanced_arith_buffers.h"
24
#include "utils/bit_tricks.h"
25
#include "utils/hash_functions.h"
26
#include "utils/memalloc.h"
27

28

29
/*
30
 * TREE MANIPULATIONS
31
 */
32

33
/*
34
 * When performing some operation f on the monomials stored in b, we
35
 * can either do a linear scan
36
 *
37
 *    for (i=1; i<b->num_nodes; i++) {
38
 *      f(b->mono + i)
39
 *    }
40
 *
41
 * or we can traverse the tree using a recursive function.
42
 *
43
 * Linear scan has a cost linear in num_nodes.
44
 *
45
 * Tree traversal has cost K * nterms * log(nterms) (approximately)
46
 * for some constant K>1.
47
 *
48
 * In most cases, the linear scan should be faster. We use a recursive
49
 * scan if num_terms is really small compared to num_nodes. The
50
 * following function is a heuristic that attempts to determine when
51
 * tree traversal is cheaper than linear scan.
52
 */
53
static bool rba_tree_is_small(const rba_buffer_t *b) {
421,154✔
54
  uint32_t n, p;
55

56
  n = b->nterms;
421,154✔
57
  p = b->num_nodes;
421,154✔
58
  return n * binlog(n) < (p >> 3);
421,154✔
59
}
60

61

62
/*
63
 * Left-most and right-most leaves of the subtree rooted at i
64
 * - special case: return null if i is null
65
 */
66
static uint32_t leftmost_leaf(const rba_buffer_t *b, uint32_t i) {
2✔
67
  uint32_t j;
68

69
  for (;;) {
70
    assert(0 <= i && i < b->num_nodes);
×
71
    j = b->child[i][0];
2✔
72
    if (j == rba_null) break;
2✔
73
    i = j;
×
74
  }
75
  return i;
2✔
76
}
77

78
static uint32_t rightmost_leaf(const rba_buffer_t *b, uint32_t i) {
18,747✔
79
  uint32_t j;
80

81
  for (;;) {
82
    assert(0 <= i && i < b->num_nodes);
980✔
83
    j = b->child[i][1];
19,727✔
84
    if (j == rba_null) break;
19,727✔
85
    i = j;
980✔
86
  }
87
  return i;
18,747✔
88
}
89

90

91
/*
92
 * Index of the main monomial (or null if the tree is empty)
93
 */
94
static inline uint32_t rba_main_idx(const rba_buffer_t *b) {
18,747✔
95
  return rightmost_leaf(b, b->root);
18,747✔
96
}
97

98

99
/*
100
 * Index of the smallest monomial (or null if the tree is empty)
101
 */
102
static inline uint32_t rba_smallest_idx(const rba_buffer_t *b) {
2✔
103
  return leftmost_leaf(b, b->root);
2✔
104
}
105

106

107
/*
108
 * Search for a node whose prod is equal to r
109
 * - return its index or rba_null if there's no such node
110
 */
111
uint32_t rba_find_node(rba_buffer_t *b, pprod_t *r) {
×
112
  uint32_t i, k;
113

114
  // to force termination: store r in the null node
115
  b->mono[0].prod = r;
×
116

117
  i = b->root;
×
118
  while (b->mono[i].prod != r) {
×
119
    k = pprod_precedes(b->mono[i].prod, r);
×
120
    assert(k <= 1);
121
    i = b->child[i][k];
×
122
  }
123

124
  return i;
×
125
}
126

127

128
/*
129
 * Check whether p is parent of q
130
 * - both must be valid node indices
131
 */
132
#ifndef NDEBUG
133
static inline bool is_parent_node(rba_buffer_t *b, uint32_t p, uint32_t q) {
134
  assert(p < b->num_nodes && q < b->num_nodes);
135
  return b->child[p][0] == q || b->child[p][1] == q;
136
}
137
#endif
138

139
/*
140
 * Child-index(p, q):
141
 * - q must be a child of node p
142
 * - returns 0 if q is the left child
143
 *   returns 1 if q is the right child
144
 * So i = child_index(b, p, q) implies b->child[p][i] = q
145
 */
146
static inline uint32_t child_index(rba_buffer_t *b, uint32_t p, uint32_t q) {
100,991✔
147
  assert(is_parent_node(b, p, q));
148
  return b->child[p][1] == q;
100,991✔
149
}
150

151

152
/*
153
 * Get sibling of q in p
154
 * - both p and q must be valid node indices
155
 * - q must be a child of p
156
 */
157
static inline uint32_t sibling(rba_buffer_t *b, uint32_t p, uint32_t q) {
66,939✔
158
  assert(is_parent_node(b, p, q));
159
  return (b->child[p][0] ^ b->child[p][1]) ^ q;
66,939✔
160
}
161

162

163
/*
164
 * Check color of node p
165
 */
166
static inline bool is_red(rba_buffer_t *b, uint32_t p) {
284,823✔
167
  assert(p < b->num_nodes);
168
  return tst_bit(b->isred, p);
284,823✔
169
}
170

171
static inline bool is_black(rba_buffer_t *b, uint32_t p) {
2,383✔
172
  return ! is_red(b, p);
2,383✔
173
}
174

175

176
/*
177
 * Set the color of node p
178
 */
179
static inline void mark_red(rba_buffer_t *b, uint32_t p) {
256,616✔
180
  assert(0 < p && p < b->num_nodes); // the null_node must always be black
181
  set_bit(b->isred, p);
256,616✔
182
}
256,616✔
183

184
static inline void mark_black(rba_buffer_t *b, uint32_t p) {
279,768✔
185
  assert(p < b->num_nodes);
186
  clr_bit(b->isred, p);
279,768✔
187
}
279,768✔
188

189
// make p the same color as q
190
static inline void copy_color(rba_buffer_t *b, uint32_t p, uint32_t q) {
262✔
191
  assert(p < b->num_nodes && q < b->num_nodes);
192
  assign_bit(b->isred, p, is_red(b, q));
262✔
193
}
262✔
194

195

196

197
/*
198
 * Fix child links in p's parent after a rotation
199
 * - p is now a child of q so p's parent must be updated to point to q
200
 * - p's parent must be the last element of b->stack
201
 */
202
static void fix_parent(rba_buffer_t *b, uint32_t p, uint32_t q) {
42,160✔
203
  uint32_t r;
204
  uint32_t i;
205

206
  r = ivector_last(&b->stack);
42,160✔
207
  if (r == rba_null) {
42,160✔
208
    assert(b->root == p);
209
    b->root = q;
26,746✔
210
  } else {
211
    i = child_index(b, r, p);
15,414✔
212
    b->child[r][i] = q;
15,414✔
213
  }
214
}
42,160✔
215

216

217
/*
218
 * Balance the tree after adding a node
219
 * - p = new node just added (must be red)
220
 * - q = parent of p
221
 * - b->stack must contains [rba_null, root, ..., r],
222
 *   which describes a path form the root to r where r = parent of q.
223
 * - the root must be black
224
 */
225
static void rba_balance_after_add(rba_buffer_t *b, uint32_t p, uint32_t q) {
202,556✔
226
  uint32_t r, s;
227
  uint32_t i, j;
228

229
  assert(is_parent_node(b, q, p) && is_red(b, p) && is_black(b, b->root));
230

231
  while (is_red(b, q)) {
214,527✔
232
    r = ivector_pop2(&b->stack); // r = parent of q
66,534✔
233
    assert(is_black(b, r));
234

235
    s = sibling(b, r, q);       // s = sibling of q = uncle of p
66,534✔
236
    if (is_red(b, s)) {
66,534✔
237
      // flip colors of q and s
238
      mark_black(b, s);
24,666✔
239
      mark_black(b, q);
24,666✔
240
      // if r is the root, we're done
241
      if (r == b->root) break;
24,666✔
242
      // otherwise, we color r red
243
      // and move up to p := r, q := parent of r
244
      mark_red(b, r);
11,971✔
245
      p = r;
11,971✔
246
      q = ivector_pop2(&b->stack); // q = parent of r
11,971✔
247
      assert(is_parent_node(b, q, p));
248

249
    } else {
250
      // Balance the tree with one or two rotations
251
      i = child_index(b, r, q);
41,868✔
252
      j = child_index(b, q, p);
41,868✔
253
      if (i != j) {
41,868✔
254
        /*
255
         * Rotate p and q
256
         * q becomes a child of p
257
         * p becomes a child of r
258
         */
259
        assert(q != 0 && p != 0 && r != 0 &&
260
               b->child[r][i] == q && b->child[q][j] == p);
261
        b->child[r][i] = p;
7,384✔
262
        b->child[q][j] = b->child[p][i];
7,384✔
263
        b->child[p][i] = q;
7,384✔
264

265
        // prepare for second rotation:
266
        q = p;
7,384✔
267
      }
268

269
      /*
270
       * rotate r and q
271
       * and fix the colors: r becomes red, q becomes black
272
       */
273
      assert(b->child[r][i] == q);
274
      fix_parent(b, r, q);
41,868✔
275
      b->child[r][i] = b->child[q][1-i];
41,868✔
276
      b->child[q][1-i] = r;
41,868✔
277
      mark_red(b, r);
41,868✔
278
      mark_black(b, q);
41,868✔
279

280
      break;
41,868✔
281
    }
282
  }
283
}
202,556✔
284

285

286
/*
287
 * Balance the tree after deleting a black node
288
 * - p = node that replaces the deleted node
289
 * - q = parent of p
290
 * - b->stack contains the path [null, root, ... r] where r is q's parent
291
 */
292
static void rba_balance_after_delete(rba_buffer_t *b, uint32_t p, uint32_t q) {
650✔
293
  uint32_t r, s, t;
294
  uint32_t i;
295

296
  assert(is_parent_node(b, q, p) && is_black(b, b->root));
297

298
 loop:
712✔
299
  if (is_red(b, p)) {
712✔
300
    mark_black(b, p);   // done
307✔
301
  } else {
302
    i = child_index(b, q, p);
405✔
303
    r = sibling(b, q, p);
405✔
304

305
    assert(is_black(b, p) && p == b->child[q][i] && r == b->child[q][1 - i]);
306

307
    if (is_red(b, r)) {
405✔
308
      // rotate and switch the colors of q and r
309
      fix_parent(b, q, r);
30✔
310
      b->child[q][1 - i] = b->child[r][i];
30✔
311
      b->child[r][i] = q;
30✔
312
      mark_black(b, r);
30✔
313
      mark_red(b, q);
30✔
314

315
      ivector_push(&b->stack, r); // r is now parent of q
30✔
316

317
      // r := new sibling of p after the rotation
318
      r = b->child[q][1 - i];
30✔
319
    }
320

321
    assert(is_black(b, r) && is_black(b, p) &&
322
           p == b->child[q][i] && r == b->child[q][1 - i]);
323

324
    // three subcases depending on r's children
325
    s = b->child[r][i];
405✔
326
    t = b->child[r][1 - i];
405✔
327
    if (is_black(b, s) && is_black(b, t)) {
405✔
328
      // two black children: change r's color to red and move up
329
      mark_red(b, r);
143✔
330
      p = q;
143✔
331
      q = ivector_pop2(&b->stack);
143✔
332
      // q is either null if p is the root (then we're done)
333
      // or q is p's parent and we loop
334
      if (q != rba_null) {
143✔
335
        assert(is_parent_node(b, q, p));
336
        goto loop;
62✔
337
      }
338

339
    } else {
340
      // at least one red child
341
      if (is_black(b, t)) {
262✔
342
        // rotate s and r
343
        // change r's color to red
344
        // change s's color to black
345
        b->child[r][i] = b->child[s][1 - i];
48✔
346
        b->child[s][1 - i] = r;
48✔
347
        b->child[q][1 - i] = s;
48✔
348
        mark_red(b, r);
48✔
349
        mark_black(b, s);
48✔
350

351
        t = r;
48✔
352
        r = s;
48✔
353
        s = b->child[r][i];
48✔
354
      }
355

356
      assert(is_black(b, p) && is_black(b, r) && is_red(b, t) &&
357
              p == b->child[q][i] && r == b->child[q][1 - i] &&
358
              s == b->child[r][i] && t == b->child[r][1 - i]);
359

360
      // rotate r and q and change colors
361
      // r takes the same color as q
362
      // t becomes black
363
      // q becomes black
364
      fix_parent(b, q, r);
262✔
365
      b->child[r][i] = q;
262✔
366
      b->child[q][1 - i] = s;
262✔
367
      copy_color(b, r, q);
262✔
368
      mark_black(b, q);
262✔
369
      mark_black(b, t);
262✔
370
    }
371
  }
372

373
  assert(is_black(b, b->root));
374
}
650✔
375

376

377
/*
378
 * BUFFER OPERATIONS
379
 */
380

381
/*
382
 * Initialize and finalize a monomial
383
 */
384
static inline void init_rba_mono(mono_t *m) {
378,937✔
385
  q_init(&m->coeff);
378,937✔
386
}
378,937✔
387

388
static inline void clear_rba_mono(mono_t *m) {
229,090✔
389
  q_clear(&m->coeff);
229,090✔
390
}
229,090✔
391

392

393
/*
394
 * Initialize buffer
395
 */
396
void init_rba_buffer(rba_buffer_t *b, pprod_table_t *ptbl) {
21,917✔
397
  uint32_t n;
398

399
  n = DEF_RBA_BUFFER_SIZE;
21,917✔
400
  assert(n <= MAX_RBA_BUFFER_SIZE);
401

402
  b->mono = (mono_t *) safe_malloc(n * sizeof(mono_t));
21,917✔
403
  b->child = (rb_node_t *) safe_malloc(n * sizeof(rb_node_t));
21,917✔
404
  b->isred = allocate_bitvector(n);
21,917✔
405

406
  b->ptbl = ptbl;
21,917✔
407
  init_ivector(&b->stack, 20);
21,917✔
408

409
  assert(n > 0 && rba_null == 0);
410

411
  // initialize the null node
412
  b->mono[0].prod = NULL;
21,917✔
413
  q_init(&b->mono[0].coeff);
21,917✔
414
  b->child[0][0] = 0;
21,917✔
415
  b->child[0][1] = 1;
21,917✔
416
  clr_bit(b->isred, 0); // null node must be black
21,917✔
417

418
  b->size = n;
21,917✔
419
  b->num_nodes = 1;
21,917✔
420
  b->nterms = 0;
21,917✔
421
  b->root = 0;      // rba_null
21,917✔
422
  b->free_list = 0; // also rba_null (empty list)
21,917✔
423
}
21,917✔
424

425

426
/*
427
 * Extend: double size
428
 */
429
static void extend_rba_buffer(rba_buffer_t *b) {
3,447✔
430
  uint32_t n;
431

432
  n = b->size << 1;
3,447✔
433
  if (n > MAX_RBA_BUFFER_SIZE) {
3,447✔
434
    out_of_memory();
×
435
  }
436

437
  b->mono = (mono_t *) safe_realloc(b->mono, n * sizeof(mono_t));
3,447✔
438
  b->child = (rb_node_t *) safe_realloc(b->child, n * sizeof(rb_node_t));
3,447✔
439
  b->isred = extend_bitvector(b->isred, n);
3,447✔
440
  b->size = n;
3,447✔
441
}
3,447✔
442

443

444
/*
445
 * Allocate a node: return its id
446
 */
447
static uint32_t rba_alloc_node(rba_buffer_t *b) {
379,806✔
448
  uint32_t i;
449

450
  i = b->free_list;
379,806✔
451
  if (i != rba_null) {
379,806✔
452
    b->free_list = b->child[i][0];
869✔
453
  } else {
454
    i = b->num_nodes;
378,937✔
455
    if (i == b->size) {
378,937✔
456
      extend_rba_buffer(b);
3,447✔
457
    }
458
    assert(i < b->size);
459
    init_rba_mono(b->mono + i);
378,937✔
460
    b->num_nodes = i+1;
378,937✔
461
  }
462

463
  assert(0 < i && i < b->num_nodes);
464

465
  return i;
379,806✔
466
}
467

468

469
/*
470
 * Free node i: add it to the free list
471
 */
472
static void rba_free_node(rba_buffer_t *b, uint32_t i) {
11,845✔
473
  assert(0 < i && i < b->num_nodes);
474
  b->child[i][0] = b->free_list;
11,845✔
475
  b->free_list = i;
11,845✔
476
}
11,845✔
477

478

479

480
/*
481
 * Scan tree and finalize all monomials
482
 * - if the tree is small, we traverse the tree
483
 * - otherwise, we use a linear scan of b->mono
484
 */
485
// recursive version: cleanup all monomials reachable from node i
486
static void cleanup_tree(rba_buffer_t *b, uint32_t i) {
3✔
487
  assert(0 <= i && i < b->num_nodes);
488
  if (i != rba_null) {
3✔
489
    clear_rba_mono(b->mono + i);
1✔
490
    cleanup_tree(b, b->child[i][0]);
1✔
491
    cleanup_tree(b, b->child[i][1]);
1✔
492
  }
493
}
3✔
494

495
static void rba_cleanup(rba_buffer_t *b) {
348,746✔
496
  uint32_t i, n;
497

498
  if (rba_tree_is_small(b)) {
348,746✔
499
    cleanup_tree(b, b->root);
1✔
500
  } else {
501
    n = b->num_nodes;
348,745✔
502
    for (i=1; i<n; i++) {
577,834✔
503
      clear_rba_mono(b->mono + i);
229,089✔
504
    }
505
  }
506
}
348,746✔
507

508

509
/*
510
 * Free memory
511
 */
512
void delete_rba_buffer(rba_buffer_t *b) {
21,917✔
513
  rba_cleanup(b);
21,917✔
514
  safe_free(b->mono);
21,917✔
515
  safe_free(b->child);
21,917✔
516
  delete_bitvector(b->isred);
21,917✔
517
  delete_ivector(&b->stack);
21,917✔
518
  b->mono = NULL;
21,917✔
519
  b->child = NULL;
21,917✔
520
  b->isred = NULL;
21,917✔
521
}
21,917✔
522

523

524

525
/*
526
 * Reset b to the empty tree
527
 */
528
void reset_rba_buffer(rba_buffer_t *b) {
326,829✔
529
  rba_cleanup(b);
326,829✔
530
  b->num_nodes = 1;
326,829✔
531
  b->nterms = 0;
326,829✔
532
  b->root = 0;
326,829✔
533
  b->free_list = 0;
326,829✔
534
}
326,829✔
535

536

537

538
/*
539
 * NODE ADDITION AND DELETION
540
 */
541

542
/*
543
 * Search for a monomial whose prod is equal to r
544
 * - if there's one return its id and set new_node to false
545
 * - if there isn't one, create a new node (with coeff = 0 and prod = r)
546
 *   and set new_node to true.
547
 *
548
 * Side effects:
549
 * - if a new node is created, num_terms is incremented
550
 * - if new_node is false, the path from the root to the returned
551
 *   node p is stored in b->stack in the form
552
 *     [rba_null, root, ...., q] where q is p's parent
553
 */
554
//static
555
uint32_t rba_get_node(rba_buffer_t *b, pprod_t *r, bool *new_node) {
399,803✔
556
  uint32_t k, i, p;
557

558
  ivector_reset(&b->stack);
399,803✔
559

560
  // to force termination, store r in the null_node2
561
  b->mono[0].prod = r;
399,803✔
562

563
  k = 0; // otherwise GCC gives a warning
399,803✔
564

565
  // invariant: p = parent of i (and we use rba_null as parent of the root)
566
  p = rba_null;
399,803✔
567
  i = b->root;
399,803✔
568
  while (b->mono[i].prod != r) {
745,633✔
569
    k = pprod_precedes(b->mono[i].prod, r);
345,830✔
570
    // save p in the stack
571
    ivector_push(&b->stack, p);
345,830✔
572
    p = i;
345,830✔
573
    i = b->child[i][k];
345,830✔
574
  }
575

576
  if (i == 0) {
399,803✔
577
    // add a new node
578
    *new_node = true;
379,797✔
579
    i = rba_alloc_node(b);
379,797✔
580

581
    b->nterms ++;
379,797✔
582

583
    b->mono[i].prod = r;
379,797✔
584
    assert(q_is_zero(&b->mono[i].coeff));
585
    b->child[i][0] = rba_null;
379,797✔
586
    b->child[i][1] = rba_null;
379,797✔
587

588
    if (p == rba_null) {
379,797✔
589
      // i becomes the root. make sure it is black
590
      b->root = i;
177,241✔
591
      mark_black(b, i);
177,241✔
592
    } else {
593
      // add i as child of p and balance the tree
594
      assert(p < b->num_nodes && b->child[p][k] == rba_null);
595
      b->child[p][k] = i;
202,556✔
596
      mark_red(b, i);
202,556✔
597
      rba_balance_after_add(b, i, p);
202,556✔
598
    }
599
  } else {
600
    // node exists; save p on the stack
601
    *new_node = false;
20,006✔
602
    ivector_push(&b->stack, p);
20,006✔
603
  }
604

605
  assert(i > 0 && b->mono[i].prod == r);
606

607
  return i;
399,803✔
608
}
609

610

611

612
/*
613
 * Delete node i
614
 * - mono[i].coeff must be zero
615
 * - b->stack must contain the path from the root to i's parent
616
 *   (as set by get_node: [null, root, ...., parent of i]
617
 *
618
 * Side effect:
619
 * - decrement b->num_terms
620
 */
621
//static
622
void rba_delete_node(rba_buffer_t *b, uint32_t i) {
11,845✔
623
  uint32_t p, j, k;
624

625
  assert(0 < i && i < b->num_nodes && q_is_zero(&b->mono[i].coeff));
626

627
  b->nterms --;
11,845✔
628

629
  if (b->child[i][0] != rba_null &&  b->child[i][1] != rba_null) {
11,845✔
630
    /*
631
     * i has two children: find the successor node of i = the node
632
     * that will be deleted. Store the path to that leaf in b->stack
633
     */
634
    p = i;
429✔
635
    j = b->child[p][1];
429✔
636
    do {
637
      ivector_push(&b->stack, p);
506✔
638
      p = j;
506✔
639
      j = b->child[j][0];
506✔
640
    } while (j != rba_null);
506✔
641

642
    assert(0 < p && p < b->num_nodes);
643

644
    /*
645
     * copy p's content into node i
646
     * we can do a direct copy of b->node[p].coeff into b->node[i].coeff
647
     * because b->mono[i].coeff is 1/0
648
     */
649
    b->mono[i].prod = b->mono[p].prod;
429✔
650
    q_copy_and_clear(&b->mono[i].coeff, &b->mono[p].coeff);
429✔
651

652
    i = p;
429✔
653
  }
654

655
  j = b->child[i][0] + b->child[i][1]; // child of i or rba_null if i has no children
11,845✔
656
  assert(j == b->child[i][0] || j == b->child[i][1]);
657

658
  p = ivector_pop2(&b->stack); // parent of i or null if i is the root
11,845✔
659

660
  if (p == rba_null) {
11,845✔
661
    assert(b->root == i);
662
    b->root = j;
10,409✔
663
    mark_black(b, j);
10,409✔
664
  } else {
665
    k = child_index(b, p, i);
1,436✔
666
    b->child[p][k] = j;
1,436✔
667

668
    if (is_black(b, i)) {
1,436✔
669
      rba_balance_after_delete(b, j, p);
650✔
670
    }
671
  }
672

673
  rba_free_node(b, i);
11,845✔
674
}
11,845✔
675

676

677

678

679

680
/*
681
 * QUERIES
682
 */
683

684
/*
685
 * Root monomial
686
 */
687
static inline mono_t *root_mono(const rba_buffer_t *b) {
898✔
688
  return b->mono + b->root;
898✔
689
}
690

691
/*
692
 * Check whether b is a constant
693
 */
694
bool rba_buffer_is_constant(const rba_buffer_t *b) {
909✔
695
  return b->nterms == 0 || (b->nterms == 1 && root_mono(b)->prod == empty_pp);
909✔
696
}
697

698
/*
699
 * Check whether b is constant and nonzero
700
 * - b must be normalized
701
 */
702
bool rba_buffer_is_nonzero(const rba_buffer_t *b) {
7✔
703
  return b->nterms == 1 && root_mono(b)->prod == empty_pp;
7✔
704
}
705

706

707
/*
708
 * Check whether b is constant and positive, negative, etc.
709
 * - b must be normalized
710
 */
711
bool rba_buffer_is_pos(const rba_buffer_t *b) {
×
712
  mono_t *r;
713
  r = root_mono(b);
×
714
  return b->nterms == 1 && r->prod == empty_pp && q_is_pos(&r->coeff);
×
715
}
716

717
bool rba_buffer_is_neg(const rba_buffer_t *b) {
×
718
  mono_t *r;
719
  r = root_mono(b);
×
720
  return b->nterms == 1 && r->prod == empty_pp && q_is_neg(&r->coeff);
×
721
}
722

723
bool rba_buffer_is_nonneg(const rba_buffer_t *b) {
×
724
  mono_t *r;
725
  r = root_mono(b);
×
726
  return b->nterms == 1 && r->prod == empty_pp && q_is_nonneg(&r->coeff);
×
727
}
728

729
bool rba_buffer_is_nonpos(const rba_buffer_t *b) {
×
730
  mono_t *r;
731
  r = root_mono(b);
×
732
  return b->nterms == 1 && r->prod == empty_pp && q_is_nonpos(&r->coeff);
×
733
}
734

735

736
/*
737
 * Check whether b is of the form 1 * X for a non-null power-product X
738
 * If so return X in *r
739
 */
740
bool rba_buffer_is_product(const rba_buffer_t *b, pprod_t **r) {
×
741
  mono_t *root;
742

743
  if (b->nterms == 1) {
×
744
    root = root_mono(b);
×
745
    if (root->prod != empty_pp && q_is_one(&root->coeff)) {
×
746
      *r = root->prod;
×
747
      return true;
×
748
    }
749
  }
750

751
  return false;
×
752
}
753

754

755
/*
756
 * Check whether b is of the form a * X - a * Y
757
 * for a non-zero rational a and two products X and Y.
758
 * If so return X in *r1 and Y in *r2
759
 */
760
bool rba_buffer_is_equality(const rba_buffer_t *b, pprod_t **r1, pprod_t **r2) {
×
761
  uint32_t i, j;
762
  mono_t *p, *q;
763
  pprod_t *x, *y;
764
  rational_t a;
765
  bool is_eq;
766

767
  is_eq = false;
×
768
  if (b->nterms == 2) {
×
769
    i = b->root;
×
770
    j = b->child[i][0] + b->child[i][1];
×
771
    assert(j == b->child[i][0] || j == b->child[i][1]);
772
    p = b->mono + i;
×
773
    q = b->mono + j;
×
774
    assert(q_is_nonzero(&p->coeff) && q_is_nonzero(&q->coeff));
775
    x = p->prod;
×
776
    y = p->prod;
×
777
    if (x != empty_pp && y != empty_pp) {
×
778
      *r1 = x;
×
779
      *r2 = y;
×
780
      q_init(&a);
×
781
      q_set(&a, &p->coeff);
×
782
      q_add(&a, &q->coeff);
×
783
      is_eq = q_is_zero(&a);
×
784
      q_clear(&a);
×
785
    }
786
  }
787

788
  return is_eq;
×
789
}
790

791

792
/*
793
 * Main monomial of b
794
 */
795
mono_t *rba_buffer_main_mono(const rba_buffer_t *b) {
18,747✔
796
  assert(b->nterms > 0);
797
  return b->mono +  rba_main_idx(b);
18,747✔
798
}
799

800

801
/*
802
 * Main term
803
 */
804
pprod_t *rba_buffer_main_term(const rba_buffer_t *b) {
18,747✔
805
  return rba_buffer_main_mono(b)->prod;
18,747✔
806
}
807

808

809
/*
810
 * Get degree of polynomial in buffer b.
811
 * - returns 0 if b is zero
812
 */
813
uint32_t rba_buffer_degree(const rba_buffer_t *b) {
19,189✔
814
  return (b->nterms == 0) ? 0 : pprod_degree(rba_buffer_main_term(b));
19,189✔
815
}
816

817

818
/*
819
 * Degree of x in b
820
 * - return 0 if x does not occur in b
821
 */
822

823
// return max(d, degree of x in subtree of root i)
824
static uint32_t tree_var_degree(const rba_buffer_t *b, int32_t x, uint32_t i, uint32_t d) {
×
825
  uint32_t e;
826

827
  if (i != rba_null) {
×
828
    assert(q_is_nonzero(&b->mono[i].coeff));
829
    e = pprod_var_degree(b->mono[i].prod, x);
×
830
    if (e > d) {
×
831
      d = e;
×
832
    }
833
    d = tree_var_degree(b, x, b->child[i][0], d);
×
834
    d = tree_var_degree(b, x, b->child[i][1], d);
×
835
  }
836
  return d;
×
837
}
838

839
uint32_t rba_buffer_var_degree(const rba_buffer_t *b, int32_t x) {
579✔
840
  uint32_t i, n, d, e;
841

842
  if (rba_tree_is_small(b)) {
579✔
843
    d = tree_var_degree(b, x, b->root, 0);
×
844
  } else {
845
    n = b->num_nodes;
579✔
846
    d = 0;
579✔
847
    for (i=1; i<n; i++) {
1,994✔
848
      if (q_is_nonzero(&b->mono[i].coeff)) {
1,415✔
849
        e = pprod_var_degree(b->mono[i].prod, x);
1,415✔
850
        if (e > d) {
1,415✔
851
          d = e;
707✔
852
        }
853
      }
854
    }
855
  }
856
  return d;
579✔
857
}
858

859

860
/*
861
 * Collect the two monomials of b into *m[0] and *m[1]
862
 * - b must have exactly two monomials
863
 */
864
void rba_buffer_monomial_pair(const rba_buffer_t *b, mono_t *m[2]) {
49,853✔
865
  uint32_t x, i, j;
866

867
  assert(b->nterms == 2);
868

869
  x = b->root;
49,853✔
870
  i = b->child[x][0];
49,853✔
871
  j = b->child[x][1];
49,853✔
872

873
  if (i == rba_null) {
49,853✔
874
    m[0] = b->mono + x;
22,028✔
875
    m[1] = b->mono + j;
22,028✔
876
  } else {
877
    assert(j == rba_null);
878
    m[0] = b->mono + i;
27,825✔
879
    m[1] = b->mono + x;
27,825✔
880
  }
881
}
49,853✔
882

883

884
/*
885
 * Monomial whose pp is equal to r (or NULL)
886
 */
887
mono_t *rba_buffer_get_mono(rba_buffer_t *b, pprod_t *r) {
×
888
  mono_t *p;
889
  uint32_t i;
890

891
  p = NULL;
×
892
  i = rba_find_node(b, r);
×
893
  if (i != rba_null) {
×
894
    p = b->mono + i;
×
895
    assert(p->prod == r && q_is_nonzero(&p->coeff));
896
  }
897
  return p;
×
898
}
899

900

901
/*
902
 * Get the constant monomial of b
903
 * - return NULL if b does not have a constant monomial
904
 */
905
mono_t *rba_buffer_get_constant_mono(const rba_buffer_t *b) {
2✔
906
  mono_t *p;
907
  uint32_t i;
908

909
  i = rba_smallest_idx(b);
2✔
910
  p = b->mono + i;
2✔
911
  if (i == 0 || p->prod != empty_pp) {
2✔
912
    p = NULL;
1✔
913
  }
914
  return p;
2✔
915
}
916

917

918

919
/*
920
 * Check whether monomial p occurs in b
921
 * - i.e., b contains a monomial with same product and coefficient as m
922
 * - m must have a non-zero coefficient
923
 */
924
static bool rba_buffer_has_monomial(rba_buffer_t *b, mono_t *p) {
×
925
  uint32_t i;
926

927
  assert(q_is_nonzero(&p->coeff));
928
  i = rba_find_node(b, p->prod);
×
929
  return i != rba_null && q_eq(&p->coeff, &b->mono[i].coeff);
×
930
}
931

932

933
/*
934
 * Check whether all monomials in b1's subtree rooted at x occur in b2
935
 */
936
static bool tree_eq(rba_buffer_t *b1, rba_buffer_t *b2, uint32_t x) {
×
937
  uint32_t i, j;
938

939
  assert(x < b1->num_nodes);
940

941
  if (x == rba_null) return true;
×
942

943
  i = b1->child[x][0];
×
944
  j = b1->child[x][1];
×
945
  return rba_buffer_has_monomial(b2, b1->mono + x) && tree_eq(b1, b2, i) && tree_eq(b1, b2, j);
×
946
}
947

948

949
/*
950
 * Check equality:
951
 * - b1 and b2 are two buffers with same number of terms
952
 * - n = number of terms
953
 */
954
static bool rba_buffer_eq(rba_buffer_t *b1, rba_buffer_t *b2) {
×
955
  rba_buffer_t *aux;
956
  mono_t *p;
957
  uint32_t n;
958

959
  assert(b1->nterms == b2->nterms);
960

961
  // swap if b1 has more nodes than b2
962
  if (b1->num_nodes > b2->num_nodes) {
×
963
    aux = b1; b1 = b2; b2 = aux;
×
964
  }
965

966
  if (rba_tree_is_small(b1)) {
×
967
    return tree_eq(b1, b2, b1->root);
×
968
  }
969

970
  p = b1->mono;
×
971
  n = b1->num_nodes - 1;
×
972
  while (n > 0) {
×
973
    n --;
×
974
    p ++;
×
975
    if (q_is_nonzero(&p->coeff) && !rba_buffer_has_monomial(b2, p)) {
×
976
      return false;
×
977
    }
978
  }
979

980
  return true;
×
981
}
982

983
/*
984
 * Check equality between b1 and b2
985
 * - both must use the same product table
986
 */
987
bool rba_buffer_equal(rba_buffer_t *b1, rba_buffer_t *b2) {
×
988
  assert(b1->ptbl == b2->ptbl);
989
  return b1->nterms  == b2->nterms && rba_buffer_eq(b1, b2);
×
990
}
991

992

993

994

995
/*****************************
996
 *  POLYNOMIAL CONSTRUCTION  *
997
 ****************************/
998

999
/*
1000
 * Set b to the constant 1
1001
 */
1002
void rba_buffer_set_one(rba_buffer_t *b) {
9✔
1003
  uint32_t i;
1004

1005
  reset_rba_buffer(b);
9✔
1006
  assert(b->root == rba_null && b->nterms == 0);
1007

1008
  i = rba_alloc_node(b);
9✔
1009

1010
  b->mono[i].prod = empty_pp;
9✔
1011
  assert(q_is_zero(&b->mono[i].coeff));
1012
  q_set_one(&b->mono[i].coeff);
9✔
1013
  b->child[i][0] = rba_null;
9✔
1014
  b->child[i][1] = rba_null;
9✔
1015

1016
  b->root = i;
9✔
1017
  mark_black(b, i);
9✔
1018

1019
  b->nterms = 1;
9✔
1020
}
9✔
1021

1022

1023
/*
1024
 * Negate: multiply all coefficients by -1
1025
 */
1026
static void negate_tree(rba_buffer_t *b, uint32_t x) {
3✔
1027
  assert(x < b->num_nodes);
1028
  if (x != rba_null) {
3✔
1029
    q_neg(&b->mono[x].coeff);
1✔
1030
    negate_tree(b, b->child[x][0]);
1✔
1031
    negate_tree(b, b->child[x][1]);
1✔
1032
  }
1033
}
3✔
1034

1035
void rba_buffer_negate(rba_buffer_t *b) {
26,514✔
1036
  uint32_t i, n;
1037

1038
  if (rba_tree_is_small(b)) {
26,514✔
1039
    negate_tree(b, b->root);
1✔
1040
  } else {
1041
    n = b->num_nodes;
26,513✔
1042
    for (i=1; i<n; i++) {
90,819✔
1043
      // Not clear whether skipping zero coeff is faster
1044
      q_neg(&b->mono[i].coeff);
64,306✔
1045
    }
1046
  }
1047
}
26,514✔
1048

1049

1050
/*
1051
 * Multiply all coefficients by constant a
1052
 */
1053
// a must be non-zero here
1054
static void mul_const_tree(rba_buffer_t *b, const rational_t *a, uint32_t x) {
×
1055
  assert(x < b->num_nodes);
1056
  if (x != rba_null) {
×
1057
    q_mul(&b->mono[x].coeff, a);
×
1058
    mul_const_tree(b, a, b->child[x][0]);
×
1059
    mul_const_tree(b, a, b->child[x][1]);
×
1060
  }
1061
}
×
1062

1063
void rba_buffer_mul_const(rba_buffer_t *b, const rational_t *a) {
8,589✔
1064
  uint32_t i, n;
1065

1066
  if (q_is_zero(a)) {
8,589✔
1067
    reset_rba_buffer(b);
129✔
1068
  } else if (rba_tree_is_small(b)) {
8,460✔
1069
    mul_const_tree(b, a, b->root);
×
1070
  } else {
1071
    n = b->num_nodes;
8,460✔
1072
    for (i=1; i<n; i++) {
17,495✔
1073
      // Skip zero coeff?
1074
      q_mul(&b->mono[i].coeff, a);
9,035✔
1075
    }
1076
  }
1077
}
8,589✔
1078

1079

1080
/*
1081
 * Divide all coefficients by a non-zero constant
1082
 */
1083
void rba_buffer_div_const(rba_buffer_t *b, const rational_t *a) {
907✔
1084
  rational_t inv_a;
1085
  uint32_t i, n;
1086

1087
  assert(q_is_nonzero(a));
1088

1089
  if (rba_tree_is_small(b)) {
907✔
1090
    q_init(&inv_a);
×
1091
    q_set(&inv_a, a);
×
1092
    q_inv(&inv_a);
×
1093
    mul_const_tree(b, &inv_a, b->root);
×
1094
    q_clear(&inv_a);
×
1095
  } else {
1096
    n = b->num_nodes;
907✔
1097
    for (i=1; i<n; i++) {
1,753✔
1098
      // Skip zero coeff?
1099
      q_div(&b->mono[i].coeff, a);
846✔
1100
    }
1101
  }
1102
}
907✔
1103

1104

1105
/*
1106
 * Take all coefficients mode m
1107
 */
1108
static void mod_const_tree(rba_buffer_t *b, const rational_t *m, uint32_t x, uint32_t *tbd_s, pprod_t **tbd) {
×
1109
  assert(q_is_integer(m) && q_is_pos(m));
1110
  assert(x < b->num_nodes);
1111
  if (x != rba_null) {
×
1112
    q_integer_rem(&b->mono[x].coeff, m);
×
1113
    if (q_is_zero(&b->mono[x].coeff)) {
×
1114
      tbd[(*tbd_s)++] = b->mono[x].prod;
×
1115
    }
1116
    mod_const_tree(b, m, b->child[x][0], tbd_s, tbd);
×
1117
    mod_const_tree(b, m, b->child[x][1], tbd_s, tbd);
×
1118
  }
1119
}
×
1120

1121
void rba_buffer_mod_const(rba_buffer_t *b, const rational_t *m) {
3,071✔
1122
  uint32_t i, j, n, tbd_s;
1123
  bool new_node;
1124

1125
  assert(q_is_integer(m) && q_is_pos(m));
1126

1127
  // to be deleted
1128
  pprod_t **tbd = safe_malloc(b->nterms * sizeof(pprod_t*));
3,071✔
1129
  tbd_s = 0;
3,071✔
1130

1131
  if (rba_tree_is_small(b)) {
3,071✔
1132
    mod_const_tree(b, m, b->root, &tbd_s, tbd);
×
1133
  } else {
1134
    n = b->num_nodes;
3,071✔
1135
    for (i = 1; i < n; i++) {
14,060✔
1136
      if (!q_is_zero(&b->mono[i].coeff)) {
10,989✔
1137
        assert(q_is_integer(&b->mono[i].coeff));
1138
        q_integer_rem(&b->mono[i].coeff, m);
10,989✔
1139
        if (q_is_zero(&b->mono[i].coeff)) {
10,989✔
1140
          tbd[tbd_s++] = b->mono[i].prod;
×
1141
        }
1142
      }
1143
    }
1144
  }
1145
  assert(tbd_s <= b->nterms);
1146
  while(tbd_s) {
3,071✔
1147
    // "find" the node to set b->stack and delete it
1148
    j = rba_get_node(b, tbd[--tbd_s], &new_node);
×
1149
    assert(!new_node);
1150
    rba_delete_node(b, j);
×
1151
  }
1152
  safe_free(tbd);
3,071✔
1153
}
3,071✔
1154

1155

1156

1157

1158
/*
1159
 * Multiply by a power product r
1160
 * - the monomial ordering is compatible with product:
1161
 *   p1 < p2 => r * p1 < r * p2
1162
 */
1163
static void mul_pp_tree(rba_buffer_t *b, pprod_t *r, uint32_t x) {
×
1164
  assert(x < b->num_nodes);
1165

1166
  if (x != rba_null) {
×
1167
    b->mono[x].prod = pprod_mul(b->ptbl, b->mono[x].prod, r);
×
1168
    mul_pp_tree(b, r, b->child[x][0]);
×
1169
    mul_pp_tree(b, r, b->child[x][1]);
×
1170
  }
1171
}
×
1172

1173
void rba_buffer_mul_pp(rba_buffer_t *b, pprod_t *r) {
17,336✔
1174
  pprod_table_t *tbl;
1175
  mono_t *p;
1176
  uint32_t n;
1177

1178
  if (rba_tree_is_small(b)) {
17,336✔
1179
    mul_pp_tree(b, r, b->root);
×
1180
  } else {
1181
    tbl = b->ptbl;
17,336✔
1182
    p = b->mono;
17,336✔
1183
    n = b->num_nodes - 1;
17,336✔
1184
    while (n > 0) {
34,533✔
1185
      n --;
17,197✔
1186
      p ++;
17,197✔
1187
      if (q_is_nonzero(&p->coeff)) {
17,197✔
1188
        p->prod = pprod_mul(tbl, p->prod, r);
17,197✔
1189
      }
1190
    }
1191
  }
1192
}
17,336✔
1193

1194

1195
/*
1196
 * Multiply by (-1) * r
1197
 */
1198
static void mul_negpp_tree(rba_buffer_t *b, pprod_t *r, uint32_t x) {
×
1199
  assert(x < b->num_nodes);
1200

1201
  if (x != rba_null) {
×
1202
    b->mono[x].prod = pprod_mul(b->ptbl, b->mono[x].prod, r);
×
1203
    q_neg(&b->mono[x].coeff);
×
1204
    mul_pp_tree(b, r, b->child[x][0]);
×
1205
    mul_pp_tree(b, r, b->child[x][1]);
×
1206
  }
1207
}
×
1208

1209
void rba_buffer_mul_negpp(rba_buffer_t *b, pprod_t *r) {
×
1210
  pprod_table_t *tbl;
1211
  mono_t *p;
1212
  uint32_t n;
1213

1214
  if (rba_tree_is_small(b)) {
×
1215
    mul_negpp_tree(b, r, b->root);
×
1216
  } else {
1217
    tbl = b->ptbl;
×
1218
    p = b->mono;
×
1219
    n = b->num_nodes - 1;
×
1220
    while (n > 0) {
×
1221
      n --;
×
1222
      p ++;
×
1223
      if (q_is_nonzero(&p->coeff)) {
×
1224
        p->prod = pprod_mul(tbl, p->prod, r);
×
1225
        q_neg(&p->coeff);
×
1226
      }
1227
    }
1228
  }
1229
}
×
1230

1231

1232

1233
/*
1234
 * Multiply by a * r
1235
 */
1236
// a must be non-zero here
1237
static void mul_mono_tree(rba_buffer_t *b, const rational_t *a, pprod_t *r, uint32_t x) {
×
1238
  assert(x < b->num_nodes);
1239

1240
  if (x != rba_null) {
×
1241
    b->mono[x].prod = pprod_mul(b->ptbl, b->mono[x].prod, r);
×
1242
    q_mul(&b->mono[x].coeff, a);
×
1243
    mul_mono_tree(b, a, r, b->child[x][0]);
×
1244
    mul_mono_tree(b, a, r, b->child[x][1]);
×
1245
  }
1246
}
×
1247

1248
void rba_buffer_mul_mono(rba_buffer_t *b, const rational_t *a, pprod_t *r) {
×
1249
  pprod_table_t *tbl;
1250
  mono_t *p;
1251
  uint32_t n;
1252

1253
  if (q_is_zero(a)) {
×
1254
    reset_rba_buffer(b);
×
1255
  } else if (rba_tree_is_small(b)) {
×
1256
    mul_mono_tree(b, a, r, b->root);
×
1257
  } else {
1258
    tbl = b->ptbl;
×
1259
    p = b->mono;
×
1260
    n = b->num_nodes - 1;
×
1261
    while (n > 0) {
×
1262
      n --;
×
1263
      p ++;
×
1264
      if (q_is_nonzero(&p->coeff)) {
×
1265
        p->prod = pprod_mul(tbl, p->prod, r);
×
1266
        q_mul(&p->coeff, a);
×
1267
      }
1268
    }
1269
  }
1270
}
×
1271

1272

1273
/*
1274
 * Add or subtract a * r when a is non-zero
1275
 */
1276
static void rba_add_mono(rba_buffer_t *b, const rational_t *a, pprod_t *r) {
144,046✔
1277
  uint32_t i;
1278
  bool new_node;
1279

1280
  assert(q_is_nonzero(a));
1281

1282
  i = rba_get_node(b, r, &new_node);
144,046✔
1283
  assert(0 < i && i < b->num_nodes && b->mono[i].prod == r);
1284
  q_add(&b->mono[i].coeff, a);
144,046✔
1285
  if (!new_node && q_is_zero(&b->mono[i].coeff)) {
144,046✔
1286
    rba_delete_node(b, i);
184✔
1287
  }
1288
}
144,046✔
1289

1290
static void rba_sub_mono(rba_buffer_t *b, const rational_t *a, pprod_t *r) {
70,317✔
1291
  uint32_t i;
1292
  bool new_node;
1293

1294
  assert(q_is_nonzero(a));
1295

1296
  i = rba_get_node(b, r, &new_node);
70,317✔
1297
  assert(0 < i && i < b->num_nodes && b->mono[i].prod == r);
1298
  q_sub(&b->mono[i].coeff, a);
70,317✔
1299
  if (!new_node && q_is_zero(&b->mono[i].coeff)) {
70,317✔
1300
    rba_delete_node(b, i);
2,607✔
1301
  }
1302
}
70,317✔
1303

1304

1305
/*
1306
 * Add or subtract a * c * r
1307
 * - a and c must be non-zero
1308
 */
1309
static void rba_addmul_mono(rba_buffer_t *b, const rational_t *a, const rational_t *c, pprod_t *r) {
1,974✔
1310
  uint32_t i;
1311
  bool new_node;
1312

1313
  assert(q_is_nonzero(a) && q_is_nonzero(c));
1314

1315
  i = rba_get_node(b, r, &new_node);
1,974✔
1316
  assert(0 < i && i < b->num_nodes && b->mono[i].prod == r);
1317
  q_addmul(&b->mono[i].coeff, a, c);
1,974✔
1318
  if (!new_node && q_is_zero(&b->mono[i].coeff)) {
1,974✔
1319
    rba_delete_node(b, i);
18✔
1320
  }
1321
}
1,974✔
1322

1323
static void rba_submul_mono(rba_buffer_t *b, const rational_t *a, const rational_t *c, pprod_t *r) {
×
1324
  uint32_t i;
1325
  bool new_node;
1326

1327
  assert(q_is_nonzero(a) && q_is_nonzero(c));
1328

1329
  i = rba_get_node(b, r, &new_node);
×
1330
  assert(0 < i && i < b->num_nodes && b->mono[i].prod == r);
1331
  q_submul(&b->mono[i].coeff, a, c);
×
1332
  if (!new_node && q_is_zero(&b->mono[i].coeff)) {
×
1333
    rba_delete_node(b, i);
×
1334
  }
1335
}
×
1336

1337

1338

1339

1340
/*
1341
 * Add or subtract monomial a * r
1342
 */
1343
void rba_buffer_add_mono(rba_buffer_t *b, const rational_t *a, pprod_t *r) {
52,391✔
1344
  if (q_is_nonzero(a)) {
52,391✔
1345
    rba_add_mono(b, a, r);
40,816✔
1346
  }
1347
}
52,391✔
1348

1349
void rba_buffer_sub_mono(rba_buffer_t *b, const rational_t *a, pprod_t *r) {
44,977✔
1350
  if (q_is_nonzero(a)) {
44,977✔
1351
    rba_sub_mono(b, a, r);
30,012✔
1352
  }
1353
}
44,977✔
1354

1355
void rba_buffer_add_const(rba_buffer_t *b, const rational_t *a) {
34,183✔
1356
  rba_buffer_add_mono(b, a, empty_pp);
34,183✔
1357
}
34,183✔
1358

1359
void rba_buffer_sub_const(rba_buffer_t *b, const rational_t *a) {
44,963✔
1360
  rba_buffer_sub_mono(b, a, empty_pp);
44,963✔
1361
}
44,963✔
1362

1363

1364

1365

1366

1367
/*
1368
 * Add or subtract r
1369
 */
1370
void rba_buffer_add_pp(rba_buffer_t *b, pprod_t *r) {
111,981✔
1371
  uint32_t i;
1372
  bool new_node;
1373

1374
  i = rba_get_node(b, r, &new_node);
111,981✔
1375
  assert(0 < i && i < b->num_nodes && b->mono[i].prod == r);
1376
  q_add_one(&b->mono[i].coeff);
111,981✔
1377
  if (!new_node && q_is_zero(&b->mono[i].coeff)) {
111,981✔
1378
    rba_delete_node(b, i);
68✔
1379
  }
1380
}
111,981✔
1381

1382
void rba_buffer_sub_pp(rba_buffer_t *b, pprod_t *r) {
71,485✔
1383
  uint32_t i;
1384
  bool new_node;
1385

1386
  i = rba_get_node(b, r, &new_node);
71,485✔
1387
  assert(0 < i && i < b->num_nodes && b->mono[i].prod == r);
1388
  q_sub_one(&b->mono[i].coeff);
71,485✔
1389
  if (!new_node && q_is_zero(&b->mono[i].coeff)) {
71,485✔
1390
    rba_delete_node(b, i);
8,968✔
1391
  }
1392
}
71,485✔
1393

1394

1395
/*
1396
 * Add b1 to b
1397
 * - the two buffers must have the same ptbl and must be distinct
1398
 * - b1 must be distinct from b
1399
 */
1400
static void add_buffer_tree(rba_buffer_t *b, rba_buffer_t *b1, uint32_t x) {
×
1401
  assert(x < b1->num_nodes);
1402
  if (x != rba_null) {
×
1403
    rba_add_mono(b, &b1->mono[x].coeff, b1->mono[x].prod);
×
1404
    add_buffer_tree(b, b1, b1->child[x][0]);
×
1405
    add_buffer_tree(b, b1, b1->child[x][1]);
×
1406
  }
1407
}
×
1408

1409
void rba_buffer_add_buffer(rba_buffer_t *b, rba_buffer_t *b1) {
11,533✔
1410
  mono_t *p;
1411
  uint32_t n;
1412

1413
  assert(b->ptbl == b1->ptbl && b != b1);
1414
  if (rba_tree_is_small(b1)) {
11,533✔
1415
    add_buffer_tree(b, b1, b1->root);
×
1416
  } else {
1417
    p = b1->mono;
11,533✔
1418
    n = b1->num_nodes - 1;
11,533✔
1419
    while (n > 0) {
33,096✔
1420
      n --;
21,563✔
1421
      p ++;
21,563✔
1422
      if (q_is_nonzero(&p->coeff)) {
21,563✔
1423
        rba_add_mono(b, &p->coeff, p->prod);
21,261✔
1424
      }
1425
    }
1426
  }
1427
}
11,533✔
1428

1429

1430
/*
1431
 * Subtract b1 from  b
1432
 * - the two buffers must have the same ptbl
1433
 * - b1 must be distinct from b
1434
 */
1435
static void sub_buffer_tree(rba_buffer_t *b, rba_buffer_t *b1, uint32_t x) {
×
1436
  assert(x < b1->num_nodes);
1437
  if (x != rba_null) {
×
1438
    rba_sub_mono(b, &b1->mono[x].coeff, b1->mono[x].prod);
×
1439
    sub_buffer_tree(b, b1, b1->child[x][0]);
×
1440
    sub_buffer_tree(b, b1, b1->child[x][1]);
×
1441
  }
1442
}
×
1443

1444
void rba_buffer_sub_buffer(rba_buffer_t *b, rba_buffer_t *b1) {
2,232✔
1445
  mono_t *p;
1446
  uint32_t n;
1447

1448
  assert(b->ptbl == b1->ptbl && b != b1);
1449

1450
  if (rba_tree_is_small(b1)) {
2,232✔
1451
    sub_buffer_tree(b, b1, b1->root);
×
1452
  } else {
1453
    p = b1->mono;
2,232✔
1454
    n = b1->num_nodes - 1;
2,232✔
1455
    while (n > 0) {
6,379✔
1456
      n --;
4,147✔
1457
      p ++;
4,147✔
1458
      if (q_is_nonzero(&p->coeff)) {
4,147✔
1459
        rba_sub_mono(b, &p->coeff, p->prod);
4,130✔
1460
      }
1461
    }
1462
  }
1463
}
2,232✔
1464

1465

1466
/*
1467
 * Add a * b1 to b
1468
 * - the two buffers must have the same ptbl
1469
 * - b1 must be distinct from b
1470
 */
1471
static void addmul_const_tree(rba_buffer_t *b, rba_buffer_t *b1, const rational_t *a, uint32_t x) {
×
1472
  assert(x < b1->num_nodes);
1473
  if (x != rba_null) {
×
1474
    rba_addmul_mono(b, a, &b1->mono[x].coeff, b1->mono[x].prod);
×
1475
    addmul_const_tree(b, b1, a, b1->child[x][0]);
×
1476
    addmul_const_tree(b, b1, a, b1->child[x][1]);
×
1477
  }
1478
}
×
1479

1480
void rba_add_const_times_buffer(rba_buffer_t *b, rba_buffer_t *b1, const rational_t *a) {
×
1481
  mono_t *p;
1482
  uint32_t n;
1483

1484
  assert(b->ptbl == b1->ptbl && b != b1);
1485

1486
  if (rba_tree_is_small(b1)) {
×
1487
    addmul_const_tree(b, b1, a, b1->root);
×
1488
  } else {
1489
    p = b1->mono;
×
1490
    n = b1->num_nodes - 1;
×
1491
    while (n > 0) {
×
1492
      n --;
×
1493
      p ++;
×
1494
      if (q_is_nonzero(&p->coeff)) {
×
1495
        rba_addmul_mono(b, a, &p->coeff, p->prod);
×
1496
      }
1497
    }
1498
  }
1499
}
×
1500

1501

1502
/*
1503
 * Subtract a * b1 from b
1504
 * - the two buffers must have the same ptbl
1505
 * - b1 must be distinct from b
1506
 */
1507
static void submul_const_tree(rba_buffer_t *b, rba_buffer_t *b1, const rational_t *a, uint32_t x) {
×
1508
  assert(x < b1->num_nodes);
1509
  if (x != rba_null) {
×
1510
    rba_submul_mono(b, a, &b1->mono[x].coeff, b1->mono[x].prod);
×
1511
    submul_const_tree(b, b1, a, b1->child[x][0]);
×
1512
    submul_const_tree(b, b1, a, b1->child[x][1]);
×
1513
  }
1514
}
×
1515

1516
void rba_sub_const_times_buffer(rba_buffer_t *b, rba_buffer_t *b1, const rational_t *a) {
×
1517
  mono_t *p;
1518
  uint32_t n;
1519

1520
  assert(b->ptbl == b1->ptbl && b != b1);
1521

1522
  if (rba_tree_is_small(b1)) {
×
1523
    submul_const_tree(b, b1, a, b1->root);
×
1524
  } else {
1525
    p = b1->mono;
×
1526
    n = b1->num_nodes - 1;
×
1527
    while (n > 0) {
×
1528
      n --;
×
1529
      p ++;
×
1530
      if (q_is_nonzero(&p->coeff)) {
×
1531
        rba_submul_mono(b, a, &p->coeff, p->prod);
×
1532
      }
1533
    }
1534
  }
1535
}
×
1536

1537

1538

1539
/*
1540
 * Add r * b1 to b
1541
 * - b1 must be different from b
1542
 */
1543
static void addmul_pp_tree(rba_buffer_t *b, rba_buffer_t *b1, pprod_t *r, uint32_t x) {
×
1544
  pprod_t *q;
1545

1546
  assert(x < b1->num_nodes);
1547

1548
  if (x != rba_null) {
×
1549
    q = pprod_mul(b1->ptbl, r, b1->mono[x].prod);
×
1550
    rba_add_mono(b, &b1->mono[x].coeff, q);
×
1551
    addmul_pp_tree(b, b1, r, b1->child[x][0]);
×
1552
    addmul_pp_tree(b, b1, r, b1->child[x][1]);
×
1553
  }
1554
}
×
1555

1556
void rba_buffer_add_pp_times_buffer(rba_buffer_t *b, rba_buffer_t *b1, pprod_t *r) {
×
1557
  pprod_table_t *tbl;
1558
  mono_t *p;
1559
  pprod_t *q;
1560
  uint32_t n;
1561

1562
  assert(b->ptbl == b1->ptbl && b != b1);
1563

1564
  if (rba_tree_is_small(b1)) {
×
1565
    addmul_pp_tree(b, b1, r, b1->root);
×
1566
  } else {
1567
    tbl = b1->ptbl;
×
1568
    p = b1->mono;
×
1569
    n = b1->num_nodes - 1;
×
1570
    while (n > 0) {
×
1571
      n --;
×
1572
      p ++;
×
1573
      if (q_is_nonzero(&p->coeff)) {
×
1574
        q = pprod_mul(tbl, r, p->prod);
×
1575
        rba_add_mono(b, &p->coeff, q);
×
1576
      }
1577
    }
1578
  }
1579
}
×
1580

1581

1582
/*
1583
 * Add - r * b1 to b
1584
 * - b1 must be different from b
1585
 */
1586
static void submul_pp_tree(rba_buffer_t *b, rba_buffer_t *b1, pprod_t *r, uint32_t x) {
×
1587
  pprod_t *q;
1588

1589
  assert(x < b1->num_nodes);
1590

1591
  if (x != rba_null) {
×
1592
    q = pprod_mul(b1->ptbl, r, b1->mono[x].prod);
×
1593
    rba_sub_mono(b, &b1->mono[x].coeff, q);
×
1594
    submul_pp_tree(b, b1, r, b1->child[x][0]);
×
1595
    submul_pp_tree(b, b1, r, b1->child[x][1]);
×
1596
  }
1597
}
×
1598

1599
void rba_buffer_sub_pp_times_buffer(rba_buffer_t *b, rba_buffer_t *b1, pprod_t *r) {
×
1600
  pprod_table_t *tbl;
1601
  mono_t *p;
1602
  pprod_t *q;
1603
  uint32_t n;
1604

1605
  assert(b->ptbl == b1->ptbl && b != b1);
1606

1607
  if (rba_tree_is_small(b1)) {
×
1608
    submul_pp_tree(b, b1, r, b1->root);
×
1609
  } else {
1610
    tbl = b1->ptbl;
×
1611
    p = b1->mono;
×
1612
    n = b1->num_nodes - 1;
×
1613
    while (n > 0) {
×
1614
      n --;
×
1615
      p ++;
×
1616
      if (q_is_nonzero(&p->coeff)) {
×
1617
        q = pprod_mul(tbl, r, p->prod);
×
1618
        rba_sub_mono(b, &p->coeff, q);
×
1619
      }
1620
    }
1621
  }
1622
}
×
1623

1624

1625
/*
1626
 * Add a * r * b1 to b
1627
 * - b1 must be different from b
1628
 */
1629
static void addmul_mono_tree(rba_buffer_t *b, rba_buffer_t *b1, const rational_t *a, pprod_t *r, uint32_t x) {
×
1630
  pprod_t *q;
1631

1632
  assert(x < b1->num_nodes);
1633

1634
  if (x != rba_null) {
×
1635
    q = pprod_mul(b1->ptbl, r, b1->mono[x].prod);
×
1636
    rba_addmul_mono(b, a, &b1->mono[x].coeff, q);
×
1637
    addmul_mono_tree(b, b1, a, r, b1->child[x][0]);
×
1638
    addmul_mono_tree(b, b1, a, r, b1->child[x][1]);
×
1639
  }
1640
}
×
1641

1642
void rba_buffer_add_mono_times_buffer(rba_buffer_t *b, rba_buffer_t *b1, const rational_t *a, pprod_t *r) {
1,580✔
1643
  pprod_table_t *tbl;
1644
  mono_t *p;
1645
  pprod_t *q;
1646
  uint32_t n;
1647

1648
  assert(b->ptbl == b1->ptbl && b != b1);
1649

1650
  if (q_is_nonzero(a)) {
1,580✔
1651
    if (rba_tree_is_small(b1)) {
1,580✔
1652
      addmul_mono_tree(b, b1, a, r, b1->root);
×
1653
    } else {
1654
      tbl = b1->ptbl;
1,580✔
1655
      p = b1->mono;
1,580✔
1656
      n = b1->num_nodes - 1;
1,580✔
1657
      while (n > 0) {
3,518✔
1658
        n--;
1,938✔
1659
        p++;
1,938✔
1660
        if (q_is_nonzero(&p->coeff)) {
1,938✔
1661
          q = pprod_mul(tbl, r, p->prod);
1,938✔
1662
          rba_addmul_mono(b, a, &p->coeff, q);
1,938✔
1663
        }
1664
      }
1665
    }
1666
  }
1667
}
1,580✔
1668

1669

1670
/*
1671
 * Add -a * r * b1 to b
1672
 * - b1 must be different from b
1673
 */
1674
static void submul_mono_tree(rba_buffer_t *b, rba_buffer_t *b1, const rational_t *a, pprod_t *r, uint32_t x) {
×
1675
  pprod_t *q;
1676

1677
  assert(x < b1->num_nodes);
1678

1679
  if (x != rba_null) {
×
1680
    q = pprod_mul(b1->ptbl, r, b1->mono[x].prod);
×
1681
    rba_submul_mono(b, a, &b1->mono[x].coeff, q);
×
1682
    submul_mono_tree(b, b1, a, r, b1->child[x][0]);
×
1683
    submul_mono_tree(b, b1, a, r, b1->child[x][1]);
×
1684
  }
1685
}
×
1686

1687
void rba_buffer_sub_mono_times_buffer(rba_buffer_t *b, rba_buffer_t *b1, const rational_t *a, pprod_t *r) {
×
1688
  pprod_table_t *tbl;
1689
  mono_t *p;
1690
  pprod_t *q;
1691
  uint32_t n;
1692

1693
  assert(b->ptbl == b1->ptbl && b != b1);
1694

1695
  if (q_is_nonzero(a)) {
×
1696
    if (rba_tree_is_small(b1)) {
×
1697
      submul_mono_tree(b, b1, a, r, b1->root);
×
1698
    } else {
1699
      tbl = b1->ptbl;
×
1700
      p = b1->mono;
×
1701
      n = b1->num_nodes - 1;
×
1702
      while (n > 0) {
×
1703
        n--;
×
1704
        p++;
×
1705
        if (q_is_nonzero(&p->coeff)) {
×
1706
          q = pprod_mul(tbl, r, p->prod);
×
1707
          rba_submul_mono(b, a, &p->coeff, q);
×
1708
        }
1709
      }
1710
    }
1711
  }
1712
}
×
1713

1714

1715
/*
1716
 * Add b1 * b2 to b
1717
 * - b1 and b2 must be distinct from b (but b1 may be equal to b2)
1718
 */
1719
static void rba_addmul_buffer_tree(rba_buffer_t *b, rba_buffer_t *b1, rba_buffer_t *b2, uint32_t x) {
×
1720
  assert(x < b2->num_nodes);
1721

1722
  if (x != rba_null) {
×
1723
    // could use more efficient versions if coeff = +/-1 or prod = empty_pp?
1724
    rba_buffer_add_mono_times_buffer(b, b1, &b2->mono[x].coeff, b2->mono[x].prod);
×
1725
    rba_addmul_buffer_tree(b, b1, b2, b2->child[x][0]);
×
1726
    rba_addmul_buffer_tree(b, b1, b2, b2->child[x][1]);
×
1727
  }
1728
}
×
1729

1730
void rba_buffer_add_buffer_times_buffer(rba_buffer_t *b, rba_buffer_t *b1, rba_buffer_t *b2) {
191✔
1731
  mono_t *p;
1732
  uint32_t n;
1733

1734
  assert(b1->ptbl == b->ptbl && b2->ptbl == b->ptbl && b != b1 && b != b2);
1735

1736
  if (rba_tree_is_small(b2)) {
191✔
1737
    rba_addmul_buffer_tree(b, b1, b2, b2->root);
×
1738
  } else {
1739
    p = b2->mono;
191✔
1740
    n = b2->num_nodes - 1;
191✔
1741
    while (n > 0) {
665✔
1742
      n --;
474✔
1743
      p ++;
474✔
1744
      if (q_is_nonzero(&p->coeff)) {
474✔
1745
        rba_buffer_add_mono_times_buffer(b, b1, &p->coeff, p->prod);
474✔
1746
      }
1747
    }
1748
  }
1749
}
191✔
1750

1751

1752
/*
1753
 * Add - b1 * b2 to b
1754
 * - b1 and b2 must be distinct from b (but b1 may be equal to b2)
1755
 */
1756
static void rba_submul_buffer_tree(rba_buffer_t *b, rba_buffer_t *b1, rba_buffer_t *b2, uint32_t x) {
×
1757
  assert(x < b2->num_nodes);
1758

1759
  if (x != rba_null) {
×
1760
    // could use more efficient versions if coeff = +/-1 or prod = empty_pp?
1761
    rba_buffer_sub_mono_times_buffer(b, b1, &b2->mono[x].coeff, b2->mono[x].prod);
×
1762
    rba_submul_buffer_tree(b, b1, b2, b2->child[x][0]);
×
1763
    rba_submul_buffer_tree(b, b1, b2, b2->child[x][1]);
×
1764
  }
1765
}
×
1766

1767
void rba_buffer_sub_buffer_times_buffer(rba_buffer_t *b, rba_buffer_t *b1, rba_buffer_t *b2) {
×
1768
  mono_t *p;
1769
  uint32_t n;
1770

1771
  assert(b1->ptbl == b->ptbl && b2->ptbl == b->ptbl && b != b1 && b != b2);
1772

1773
  if (rba_tree_is_small(b2)) {
×
1774
    rba_submul_buffer_tree(b, b1, b2, b2->root);
×
1775
  } else {
1776
    p = b2->mono;
×
1777
    n = b2->num_nodes - 1;
×
1778
    while (n > 0) {
×
1779
      n --;
×
1780
      p ++;
×
1781
      if (q_is_nonzero(&p->coeff)) {
×
1782
        rba_buffer_sub_mono_times_buffer(b, b1, &p->coeff, p->prod);
×
1783
      }
1784
    }
1785
  }
1786
}
×
1787

1788

1789

1790
/*
1791
 * Multiply b by b1
1792
 */
1793
void rba_buffer_mul_buffer(rba_buffer_t *b, rba_buffer_t *b1) {
191✔
1794
  rba_buffer_t aux;
1795

1796
  assert(b->ptbl == b1->ptbl);
1797

1798
  aux = *b;  // clone of b
191✔
1799
  init_rba_buffer(b, aux.ptbl);
191✔
1800
  rba_buffer_add_buffer_times_buffer(b, &aux, b1);
191✔
1801
  delete_rba_buffer(&aux);
191✔
1802
}
191✔
1803

1804

1805
/*
1806
 * Compute the square of b
1807
 */
1808
void rba_buffer_square(rba_buffer_t *b) {
×
1809
  rba_buffer_t aux;
1810

1811
  aux = *b;
×
1812
  init_rba_buffer(b, aux.ptbl);
×
1813
  rba_buffer_add_buffer_times_buffer(b, &aux, &aux);
×
1814
  delete_rba_buffer(&aux);
×
1815
}
×
1816

1817

1818

1819

1820

1821

1822
/*************************************
1823
 *  OPERATIONS WITH MONOMIAL ARRAYS  *
1824
 ************************************/
1825

1826
/*
1827
 * Add poly to buffer b
1828
 */
1829
void rba_buffer_add_monarray(rba_buffer_t *b, monomial_t *poly, pprod_t **pp) {
33,078✔
1830
  while (poly->var < max_idx) {
115,047✔
1831
    rba_add_mono(b, &poly->coeff, *pp);
81,969✔
1832
    poly ++;
81,969✔
1833
    pp ++;
81,969✔
1834
  }
1835
}
33,078✔
1836

1837

1838
/*
1839
 * Subtract poly from buffer b
1840
 */
1841
void rba_buffer_sub_monarray(rba_buffer_t *b, monomial_t *poly, pprod_t **pp) {
14,898✔
1842
  while (poly->var < max_idx) {
51,073✔
1843
    rba_sub_mono(b, &poly->coeff, *pp);
36,175✔
1844
    poly ++;
36,175✔
1845
    pp ++;
36,175✔
1846
  }
1847
}
14,898✔
1848

1849

1850
/*
1851
 * Add a * poly to buffer b
1852
 */
1853
void rba_buffer_add_const_times_monarray(rba_buffer_t *b, monomial_t *poly, pprod_t **pp, const rational_t *a) {
13✔
1854
  if (q_is_nonzero(a)) {
13✔
1855
    while (poly->var < max_idx) {
49✔
1856
      rba_addmul_mono(b, a, &poly->coeff, *pp);
36✔
1857
      poly ++;
36✔
1858
      pp ++;
36✔
1859
    }
1860
  }
1861
}
13✔
1862

1863

1864
/*
1865
 * Subtract a * poly from b
1866
 */
1867
void rba_buffer_sub_const_times_monarray(rba_buffer_t *b, monomial_t *poly, pprod_t **pp, const rational_t *a) {
×
1868
  if (q_is_nonzero(a)) {
×
1869
    while (poly->var < max_idx) {
×
1870
      rba_submul_mono(b, a, &poly->coeff, *pp);
×
1871
      poly ++;
×
1872
      pp ++;
×
1873
    }
1874
  }
1875
}
×
1876

1877

1878
/*
1879
 * Add a * r * poly to b
1880
 */
1881
void rba_buffer_add_mono_times_monarray(rba_buffer_t *b, monomial_t *poly, pprod_t **pp, const rational_t *a, pprod_t *r) {
×
1882
  pprod_table_t *tbl;
1883
  pprod_t *q;
1884

1885
  if (q_is_nonzero(a)) {
×
1886
    tbl = b->ptbl;
×
1887
    while (poly->var < max_idx) {
×
1888
      q = pprod_mul(tbl, r, *pp);
×
1889
      rba_addmul_mono(b, a, &poly->coeff, q);
×
1890
      poly ++;
×
1891
      pp ++;
×
1892
    }
1893
  }
1894
}
×
1895

1896

1897
/*
1898
 * Add -a * r * poly to b
1899
 */
1900
void rba_buffer_sub_mono_times_monarray(rba_buffer_t *b, monomial_t *poly, pprod_t **pp, const rational_t *a, pprod_t *r) {
×
1901
  pprod_table_t *tbl;
1902
  pprod_t *q;
1903

1904
  if (q_is_nonzero(a)) {
×
1905
    tbl = b->ptbl;
×
1906
    while (poly->var < max_idx) {
×
1907
      q = pprod_mul(tbl, r, *pp);
×
1908
      rba_submul_mono(b, a, &poly->coeff, q);
×
1909
      poly ++;
×
1910
      pp ++;
×
1911
    }
1912
  }
1913
}
×
1914

1915

1916
/*
1917
 * Multiply b by poly
1918
 */
1919
void rba_buffer_mul_monarray(rba_buffer_t *b, monomial_t *poly, pprod_t **pp) {
676✔
1920
  rba_buffer_t aux;
1921

1922
  aux = *b;
676✔
1923
  init_rba_buffer(b, aux.ptbl);
676✔
1924
  while (poly->var < max_idx) {
1,782✔
1925
    rba_buffer_add_mono_times_buffer(b, &aux, &poly->coeff, *pp);
1,106✔
1926
    poly ++;
1,106✔
1927
    pp ++;
1,106✔
1928
  }
1929
  delete_rba_buffer(&aux);
676✔
1930
}
676✔
1931

1932

1933
/*
1934
 * Multiply b by  poly ^ d
1935
 * - pp = power products for the variables of poly
1936
 * - use aux as an auxiliary buffer (aux must be distinct from b)
1937
 * - store the result in b (normalized)
1938
 */
1939
void rba_buffer_mul_monarray_power(rba_buffer_t *b, monomial_t *poly, pprod_t **pp, uint32_t d, rba_buffer_t *aux) {
×
1940
  uint32_t i;
1941

1942
  assert(b != aux && b->ptbl == aux->ptbl);
1943

1944
  if (d <= 4) {
×
1945
    // small exponent: aux is not used
1946
    for (i=0; i<d; i++) {
×
1947
      rba_buffer_mul_monarray(b, poly, pp);
×
1948
    }
1949
  } else {
1950
    // larger exponent
1951
    reset_rba_buffer(aux);
×
1952
    rba_buffer_add_monarray(aux, poly, pp); // aux := poly
×
1953
    for (;;) {
1954
      /*
1955
       * loop invariant: b0 * p^d0 == b * aux^ d
1956
       * with b0 = b on entry to the function
1957
       *      d0 = d on entry to the function
1958
       */
1959
      assert(d > 0);
×
1960
      if ((d & 1) != 0) {
×
1961
        rba_buffer_mul_buffer(b, aux); // b := b * aux
×
1962
      }
1963
      d >>= 1;                         // d := d/2
×
1964
      if (d == 0) break;
×
1965
      rba_buffer_square(aux);          // aux := aux^2
×
1966
    }
1967
  }
1968
}
×
1969

1970

1971

1972
/*******************************************************************
1973
 *  SUPPORT FOR HASH CONSING AND CONVERSION TO POLYNOMIAL OBJECTS  *
1974
 ******************************************************************/
1975

1976
/*
1977
 * The conversion of a buffer b to a polynomial object requires two steps:
1978
 * 1) convert all the power-products in b to integer indices.
1979
 *    This must map empty_pp to const_idx and end_pp to max_idx.
1980
 * 2) build a polynomial from the coefficients of b and the integer indices
1981
 *
1982
 * The operations below use a buffer b and an integer array v.
1983
 * The array v stores the conversion from power-products to integer indices:
1984
 * If b contains a_0 r_0 + ... + a_n r_n then v must have (n+2) elements
1985
 * and the integer index for power product r_i is v[i], and the last element
1986
 * of v must be max_idx.
1987
 *
1988
 * The pair (b, v) defines then a polynomial P(b, v) = a_1 v[1] + ... + a_n v[n],
1989
 */
1990

1991
/*
1992
 * Store the subterm of P(b, v) rooted at x into polynomial p
1993
 * - i = number of terms to the left of subtree rooted at x
1994
 * - return i + number of terms in the subtree rooted at x
1995
 */
1996
static uint32_t rba_copy_tree(polynomial_t *p, rba_buffer_t *b, int32_t *v, uint32_t i, uint32_t x) {
352,503✔
1997
  assert(x < b->num_nodes);
1998

1999
  if (x != rba_null) {
352,503✔
2000
    i = rba_copy_tree(p, b, v, i, b->child[x][0]);
149,361✔
2001
    assert(i < p->nterms);
2002
    p->mono[i].var = v[i];
149,361✔
2003
    q_copy_and_clear(&p->mono[i].coeff, &b->mono[x].coeff);
149,361✔
2004
    i = rba_copy_tree(p, b, v, i+1, b->child[x][1]);
149,361✔
2005
  }
2006

2007
  return i;
352,503✔
2008
}
2009

2010

2011
/*
2012
 * Build P(b, v) (i.e., convert b to a polynomial then reset b).
2013
 * SIDE EFFECT: b is reset to the zero polynomial.
2014
 */
2015
#ifdef NDEBUG
2016
polynomial_t *rba_buffer_get_poly(rba_buffer_t *b, int32_t *v) {
53,781✔
2017
  polynomial_t *tmp;
2018

2019
  tmp = alloc_raw_polynomial(b->nterms);
53,781✔
2020
  (void) rba_copy_tree(tmp, b, v, 0, b->root);
53,781✔
2021

2022
  // reset b but don't call cleanup
2023
  b->num_nodes = 1;
53,781✔
2024
  b->nterms = 0;
53,781✔
2025
  b->root = 0;
53,781✔
2026
  b->free_list = 0;
53,781✔
2027

2028
  return tmp;
53,781✔
2029
}
2030

2031
#else
2032

2033
/*
2034
 * Debugging enabled
2035
 */
2036

2037
// check that all monomials are cleared
2038
static bool rba_buffer_is_clean(rba_buffer_t *b) {
2039
  uint32_t i, n;
2040

2041
  n = b->num_nodes;
2042
  for (i=1; i<n; i++) {
2043
    if (q_is_nonzero(&b->mono[i].coeff)) {
2044
      return false;
2045
    }
2046
  }
2047
  return true;
2048
}
2049

2050
// same function with debugging
2051
polynomial_t *rba_buffer_get_poly(rba_buffer_t *b, int32_t *v) {
2052
  polynomial_t *tmp;
2053
  uint32_t n;
2054

2055
  tmp = alloc_raw_polynomial(b->nterms);
2056
  n = rba_copy_tree(tmp, b, v, 0, b->root);
2057
  assert(n == b->nterms);
2058

2059
  // reset b but don't call cleanup
2060
  assert(rba_buffer_is_clean(b));
2061

2062
  b->num_nodes = 1;
2063
  b->nterms = 0;
2064
  b->root = 0;
2065
  b->free_list = 0;
2066

2067
  return tmp;
2068
}
2069

2070

2071
#endif
2072

2073

2074
/*
2075
 * Hash code support: iterate the hash code computation
2076
 * through all nodes reachable from x (in monomial order)
2077
 * - *i = number of terms to the left of the subtree rooted at x
2078
 * - h = hash code for this subtree
2079
 * - update i: add the number of terms in the subtree rooted at x
2080
 */
2081
static uint32_t rba_hash_tree(rba_buffer_t *b, int32_t *v, uint32_t *i, uint32_t h, uint32_t x) {
538,701✔
2082
  uint32_t num, den, j;
2083

2084
  assert(x < b->num_nodes);
2085

2086
  if (x != rba_null) {
538,701✔
2087
    h = rba_hash_tree(b, v, i, h, b->child[x][0]); // left subtree
226,436✔
2088

2089
    // apply hash for node x
2090
    q_hash_decompose(&b->mono[x].coeff, &num, &den);
226,436✔
2091
    j = *i;
226,436✔
2092
    assert(j < b->nterms);
2093
    h = jenkins_hash_triple(v[j], num, den, h);
226,436✔
2094
    *i = j+1;
226,436✔
2095

2096
    h = rba_hash_tree(b, v, i, h, b->child[x][1]); // right subtree
226,436✔
2097
  }
2098

2099
  return h;
538,701✔
2100
}
2101

2102

2103
/*
2104
 * Hash code for P(b, v).
2105
 * This function is consistent with hash_polynomial defined in polynomials.c:
2106
 * If P(b, v) = p0 then hash_rba_buffer(b, v) = hash_polynomial(p0).
2107
 */
2108
uint32_t hash_rba_buffer(rba_buffer_t *b, int32_t *v) {
85,829✔
2109
  uint32_t h, n;
2110

2111
  n = 0;
85,829✔
2112
  h = rba_hash_tree(b, v, &n, HASH_POLY_SEED + b->nterms, b->root);
85,829✔
2113
  assert(n == b->nterms);
2114
  return h;
85,829✔
2115
}
2116

2117

2118

2119
/*
2120
 * Check that the subtree rooted at x is equal to a segment of p
2121
 * that start at *i:
2122
 * - if the subtree rooted at x has n nodes then this returns true
2123
 *   if the subtree is equal to p[j ... j+n-1] where j = *i
2124
 * - side effect: if the function returns true then *i is updated to j+n-1
2125
 */
2126
// aux function: check where p->mono[*i] is equal to the node x
2127
// if so increment *i
2128
static bool rba_equal_node(const polynomial_t *p, const rba_buffer_t *b, int32_t *v, uint32_t *i, uint32_t x) {
77,075✔
2129
  uint32_t j;
2130

2131
  assert(0 < x && x < b->num_nodes && q_is_nonzero(&b->mono[x].coeff));
2132

2133
  j = *i;
77,075✔
2134
  assert(j < p->nterms);
2135

2136
  if (v[j] == p->mono[j].var && q_eq(&b->mono[x].coeff, &p->mono[j].coeff)) {
77,075✔
2137
    *i = j+1;
77,075✔
2138
    return true;
77,075✔
2139
  }
2140

2141
  return false;
×
2142
}
2143

2144
static bool rba_equal_tree(const polynomial_t *p, const rba_buffer_t *b, int32_t *v, uint32_t *i, uint32_t x) {
186,198✔
2145
  assert(x < b->num_nodes);
2146
  return (x == rba_null) ||
340,348✔
2147
    (rba_equal_tree(p, b, v, i, b->child[x][0]) &&
154,150✔
2148
     rba_equal_node(p, b, v, i, x) &&
154,150✔
2149
     rba_equal_tree(p, b, v, i, b->child[x][1]));
77,075✔
2150
}
2151

2152

2153
/*
2154
 * Check where P(b, v) is equal to p
2155
 */
2156
bool rba_buffer_equal_poly(const rba_buffer_t *b, int32_t *v, const polynomial_t *p) {
32,048✔
2157
  uint32_t n;
2158
  bool result;
2159

2160
  result = false;
32,048✔
2161
  if (p->nterms == b->nterms) {
32,048✔
2162
    n = 0;
32,048✔
2163
    result = rba_equal_tree(p, b, v, &n, b->root);
32,048✔
2164
    assert(!result || n == b->nterms);
2165
  }
2166

2167
  return result;
32,048✔
2168
}
2169

2170

2171

2172
/*
2173
 * TYPE CHECKING
2174
 */
2175

2176
/*
2177
 * All functions use an external function to check the type of variables
2178
 * - for every variable x, var_is_int(aux, x) must return true if x is
2179
 *   integer, false if x is real.
2180
 */
2181

2182

2183
/*
2184
 * Check whether monomial m is integral:
2185
 */
2186
static bool monomial_is_int(const mono_t *m, void *aux, var_type_fun_t var_is_int) {
8✔
2187
  pprod_t *p;
2188
  uint32_t i, n;
2189

2190
  if (q_is_zero(&m->coeff)) {
8✔
2191
    return true;
×
2192
  }
2193

2194
  if (!q_is_integer(&m->coeff)) {
8✔
2195
    return false;
2✔
2196
  }
2197

2198
  p = m->prod;
6✔
2199
  if (pp_is_empty(p)) {
6✔
2200
    return true;
×
2201
  }
2202

2203
  if (pp_is_var(p)) {
6✔
2204
    return var_is_int(aux, var_of_pp(p));
6✔
2205
  }
2206

2207
  n = p->len;
×
2208
  for (i=0; i<n; i++) {
×
2209
    if (! var_is_int(aux, p->prod[i].var)) {
×
2210
      return false;
×
2211
    }
2212
  }
2213

2214
  return true;
×
2215
}
2216

2217

2218
/*
2219
 * Check whether all monomials in x's subtree are integral
2220
 */
2221
static bool tree_is_int(const rba_buffer_t *b, uint32_t x, void *aux, var_type_fun_t var_is_int) {
×
2222
  return x == rba_null ||
×
2223
    (monomial_is_int(b->mono + x, aux, var_is_int) &&
×
2224
     tree_is_int(b, b->child[x][0], aux, var_is_int) &&
×
2225
     tree_is_int(b, b->child[x][1], aux, var_is_int));
×
2226
}
2227

2228
/*
2229
 * Check whether b is an integral polynomial
2230
 */
2231
bool rba_buffer_is_int(const rba_buffer_t *b, void *aux, var_type_fun_t var_is_int) {
5✔
2232
  if (rba_tree_is_small(b)) {
5✔
2233
    return tree_is_int(b, b->root, aux, var_is_int);
×
2234
  } else {
2235
    uint32_t n = b->num_nodes;
5✔
2236
    for (uint32_t i=1; i<n; i++) {
11✔
2237
      if (!monomial_is_int(&b->mono[i], aux, var_is_int)) {
8✔
2238
        return false;
2✔
2239
      }
2240
    }
2241
    return true;
3✔
2242
  }
2243
}
2244

2245
static inline bool is_mod(const rational_t *r, const rational_t *mod) {
×
2246
  return q_is_integer(r) && q_is_nonneg(r) && q_lt(r, mod);
×
2247
}
2248

2249
static bool tree_is_mod(const rba_buffer_t *b, uint32_t x, const rational_t *mod) {
×
2250
  return x == rba_null ||
×
2251
    (is_mod(&b->mono[x].coeff, mod) &&
×
2252
     tree_is_mod(b, b->child[x][0], mod) &&
×
2253
     tree_is_mod(b, b->child[x][1], mod));
×
2254
}
2255

2256
/*
2257
 * Check whether the every coefficient c of b is int and 0 <= c < mod
2258
 */
2259
bool rba_buffer_is_mod(const rba_buffer_t *b, const rational_t *mod) {
×
2260
  assert(q_is_integer(mod) && q_is_pos(mod));
2261

2262
  if (rba_tree_is_small(b)) {
×
2263
    return tree_is_mod(b, b->root, mod);
×
2264
  } else {
2265
    uint32_t n = b->num_nodes;
×
2266
    for (uint32_t i=1; i<n; i++) {
×
2267
      if (!is_mod(&b->mono[i].coeff, mod)) {
×
2268
        return false;
×
2269
      }
2270
    }
2271
    return true;
×
2272
  }
2273
}
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

© 2025 Coveralls, Inc