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 * INTERVALS OF BIT-VECTOR VALUES
21 */
22
23 #include "solvers/bv/bv_intervals.h"
24 #include "utils/memalloc.h"
25
26 /*
27 * AUXILIARY BUFFERS
28 */
29
30 /*
31 * Initialization: nothing is allocated.
32 * - all buffers are initialized to NULL
33 * - aux->size is 0
34 */
init_bv_aux_buffers(bv_aux_buffers_t * aux)35 void init_bv_aux_buffers(bv_aux_buffers_t *aux) {
36 aux->buffer_a = NULL;
37 aux->buffer_b = NULL;
38 aux->buffer_c = NULL;
39 aux->buffer_d = NULL;
40 aux->size = 0;
41 }
42
43
44 /*
45 * Deletion: free memory
46 */
delete_bv_aux_buffers(bv_aux_buffers_t * aux)47 void delete_bv_aux_buffers(bv_aux_buffers_t *aux) {
48 safe_free(aux->buffer_a);
49 safe_free(aux->buffer_b);
50 safe_free(aux->buffer_c);
51 safe_free(aux->buffer_d);
52 aux->buffer_a = NULL;
53 aux->buffer_b = NULL;
54 aux->buffer_c = NULL;
55 aux->buffer_d = NULL;
56 aux->size = 0;
57 }
58
59
60 /*
61 * Resize: make sure all buffers are large enough
62 * for at least n words
63 */
bv_aux_buffers_set_size(bv_aux_buffers_t * aux,uint32_t n)64 static void bv_aux_buffers_set_size(bv_aux_buffers_t *aux, uint32_t n) {
65 if (aux->size < n) {
66 if (n < BV_INTERVAL_DEF_SIZE) {
67 n = BV_INTERVAL_DEF_SIZE;
68 }
69 assert(n <= BV_INTERVAL_MAX_SIZE);
70 aux->buffer_a = (uint32_t *) safe_realloc(aux->buffer_a, n * sizeof(uint32_t));
71 aux->buffer_b = (uint32_t *) safe_realloc(aux->buffer_b, n * sizeof(uint32_t));
72 aux->buffer_c = (uint32_t *) safe_realloc(aux->buffer_c, n * sizeof(uint32_t));
73 aux->buffer_d = (uint32_t *) safe_realloc(aux->buffer_d, n * sizeof(uint32_t));
74 aux->size = n;
75 }
76 }
77
78
79
80 /*
81 * Compute a + b * c using aux
82 * - a, b, and c must all be normalized modulo 2^n
83 * - a, b, and c are interpreted as unsigned integers
84 * - aux->size must be large enough to store bitvectors of size 2*n
85 * - the result is stored in aux->buffer_a as a bitvector of size 2*n
86 * - side effect: use buffer_c and buffer_d
87 */
bv_aux_addmul_u(bv_aux_buffers_t * aux,uint32_t * a,uint32_t * b,uint32_t * c,uint32_t n)88 static void bv_aux_addmul_u(bv_aux_buffers_t *aux, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t n) {
89 uint32_t n2, w;
90
91 n2 = n + n;
92 w = (n2 + 31) >> 5;
93 assert(aux->size >= w);
94
95 bvconst_set_extend(aux->buffer_a, n2, a, n, 0); // buffer_a := zero_extend a to size 2n
96 bvconst_set_extend(aux->buffer_c, n2, b, n, 0); // buffer_c := zero_extend b
97 bvconst_set_extend(aux->buffer_d, n2, c, n, 0); // buffer_d := zero_extend c
98
99 bvconst_addmul(aux->buffer_a, w, aux->buffer_c, aux->buffer_d); // buffer_a := buffer_a + buffer_c * buffer_d
100 bvconst_normalize(aux->buffer_a, n2);
101 }
102
103
104
105 /*
106 * Same thing for a - b * c
107 */
bv_aux_submul_u(bv_aux_buffers_t * aux,uint32_t * a,uint32_t * b,uint32_t * c,uint32_t n)108 static void bv_aux_submul_u(bv_aux_buffers_t *aux, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t n) {
109 uint32_t n2, w;
110
111 n2 = n + n;
112 w = (n2 + 31) >> 5;
113 assert(aux->size >= w);
114
115 bvconst_set_extend(aux->buffer_a, n2, a, n, 0); // buffer_a := zero_extend a to size 2n
116 bvconst_set_extend(aux->buffer_c, n2, b, n, 0); // buffer_c := zero_extend b
117 bvconst_set_extend(aux->buffer_d, n2, c, n, 0); // buffer_d := zero_extend c
118
119 bvconst_submul(aux->buffer_a, w, aux->buffer_c, aux->buffer_d); // buffer_a := buffer_a + buffer_c * buffer_d
120 bvconst_normalize(aux->buffer_a, n2);
121 }
122
123
124 /*
125 * Same thing for a + b * c, this time interpreted as signed integers
126 */
bv_aux_addmul_s(bv_aux_buffers_t * aux,uint32_t * a,uint32_t * b,uint32_t * c,uint32_t n)127 static void bv_aux_addmul_s(bv_aux_buffers_t *aux, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t n) {
128 uint32_t n2, w;
129
130 n2 = n + n;
131 w = (n2 + 31) >> 5;
132 assert(aux->size >= w);
133
134 bvconst_set_extend(aux->buffer_a, n2, a, n, -1); // buffer_a := sign_extend a to size 2n
135 bvconst_set_extend(aux->buffer_c, n2, b, n, -1); // buffer_c := sign_extend b
136 bvconst_set_extend(aux->buffer_d, n2, c, n, -1); // buffer_d := sign_extend c
137
138 bvconst_addmul(aux->buffer_a, w, aux->buffer_c, aux->buffer_d); // buffer_a := buffer_a + buffer_c * buffer_d
139 bvconst_normalize(aux->buffer_a, n2);
140 }
141
142
143 /*
144 * Swap buffer_a and buffer_b
145 */
bv_aux_swap_ab(bv_aux_buffers_t * aux)146 static inline void bv_aux_swap_ab(bv_aux_buffers_t *aux) {
147 uint32_t *tmp;
148
149 tmp = aux->buffer_a;
150 aux->buffer_a = aux->buffer_b;
151 aux->buffer_b = tmp;
152 }
153
154
155 /*
156 * Shift buffer_a right by n bits and store the result in buffer_c
157 * then normalize buffer_a modulo 2^n.
158 * This stores the quotient of buffer_a by 2^n in buffer_c
159 * and the remainder of buffer_a divided by 2^n in buffer_a.
160 */
bv_aux_shift_a_to_c(bv_aux_buffers_t * aux,uint32_t n)161 static inline void bv_aux_shift_a_to_c(bv_aux_buffers_t *aux, uint32_t n) {
162 uint32_t n2;
163 uint32_t w;
164
165 n2 = n + n;
166 w = (n2 + 31) >> 5;
167 assert(aux->size >= w);
168 bvconst_set(aux->buffer_c, w, aux->buffer_a); // buffer_c := buffer_a
169 bvconst_shift_right(aux->buffer_c, n2, n, 0); // buffer_c := quotient
170 bvconst_normalize(aux->buffer_a, n); // buffer_a := remainder
171 }
172
173 /*
174 * Shift buffer_b right by n bits and store the result in buffer_d
175 * then normalize buffer_b modulo 2^n.
176 * This stores the quotient of buffer_b by 2^n in buffer_d
177 * and the remainder of buffer_b divided by 2^n in buffer_b.
178 */
bv_aux_shift_b_to_d(bv_aux_buffers_t * aux,uint32_t n)179 static inline void bv_aux_shift_b_to_d(bv_aux_buffers_t *aux, uint32_t n) {
180 uint32_t n2;
181 uint32_t w;
182
183 n2 = n + n;
184 w = (n2 + 31) >> 5;
185 assert(aux->size >= w);
186 bvconst_set(aux->buffer_d, w, aux->buffer_b); // buffer_d := buffer_b
187 bvconst_shift_right(aux->buffer_d, n2, n, 0); // buffer_d := quotient
188 bvconst_normalize(aux->buffer_b, n); // buffer_b := remainder
189 }
190
191
192 /*
193 * INTERVALS
194 */
195
196 /*
197 * Initialization: don't allocate anything yet.
198 * - nbits, width, and size are set to 0
199 * - the arrays are allocated on the first call to resize
200 */
init_bv_interval(bv_interval_t * intv)201 void init_bv_interval(bv_interval_t *intv) {
202 intv->low = NULL;
203 intv->high = NULL;
204 intv->nbits = 0;
205 intv->width = 0;
206 intv->size = 0;
207 }
208
209
210 /*
211 * Free memory and reset
212 */
delete_bv_interval(bv_interval_t * intv)213 void delete_bv_interval(bv_interval_t *intv) {
214 safe_free(intv->low);
215 safe_free(intv->high);
216 intv->low = NULL;
217 intv->high = NULL;
218 intv->nbits = 0;
219 intv->width = 0;
220 intv->size = 0;
221 }
222
223
224 /*
225 * Make sure array low/high are large enough to store n words
226 * - n must be no more than BV_INTERVAL_MAX_SIZE
227 */
bv_interval_set_size(bv_interval_t * intv,uint32_t n)228 static void bv_interval_set_size(bv_interval_t *intv, uint32_t n) {
229 if (intv->size < n) {
230 if (n < BV_INTERVAL_DEF_SIZE) {
231 n = BV_INTERVAL_DEF_SIZE;
232 }
233 assert(n <= BV_INTERVAL_MAX_SIZE);
234 intv->low = (uint32_t *) safe_realloc(intv->low, n * sizeof(uint32_t));
235 intv->high = (uint32_t *) safe_realloc(intv->high, n * sizeof(uint32_t));
236 intv->size = n;
237 }
238 }
239
240
241 /*
242 * Make sure the arrays low/high are large enough for n bits
243 */
resize_bv_interval(bv_interval_t * intv,uint32_t n)244 void resize_bv_interval(bv_interval_t *intv, uint32_t n) {
245 uint32_t w;
246
247 w = (n + 31) >> 5; // number of words = ceil(n/32)
248 bv_interval_set_size(intv, w);
249 assert(intv->size >= w);
250 intv->nbits = n;
251 intv->width = w;
252 }
253
254
255 /*
256 * Initialize intv to [x, x]
257 * - n must be positive
258 * - x must be normalized modulo 2^n (cf. bv_constants.h)
259 */
bv_point_interval(bv_interval_t * intv,uint32_t * x,uint32_t n)260 void bv_point_interval(bv_interval_t *intv, uint32_t *x, uint32_t n) {
261 assert(n > 0 && bvconst_is_normalized(x, n));
262
263 resize_bv_interval(intv, n);
264 bvconst_set(intv->low, intv->width, x);
265 bvconst_set(intv->high, intv->width, x);
266 }
267
268
269 /*
270 * Initialize intv to [0, 0]
271 * - n must be positive
272 */
bv_zero_interval(bv_interval_t * intv,uint32_t n)273 void bv_zero_interval(bv_interval_t *intv, uint32_t n) {
274 assert(n > 0);
275
276 resize_bv_interval(intv, n);
277 bvconst_clear(intv->low, intv->width);
278 bvconst_clear(intv->high, intv->width);
279 }
280
281
282 /*
283 * Initialize to the interval [x, y] (unsigned)
284 * - n must be positive
285 * - x and y must be normalized modulo 2^n
286 * - x <= y must hold
287 * - the arrays are resized if necessary
288 */
bv_interval_set_u(bv_interval_t * intv,uint32_t * x,uint32_t * y,uint32_t n)289 void bv_interval_set_u(bv_interval_t *intv, uint32_t *x, uint32_t *y, uint32_t n) {
290 assert(n > 0 && bvconst_is_normalized(x, n) && bvconst_is_normalized(y, n) &&
291 bvconst_le(x, y, n));
292
293 resize_bv_interval(intv, n);
294 bvconst_set(intv->low, intv->width, x);
295 bvconst_set(intv->high, intv->width, y);
296 }
297
298
299 /*
300 * Initialize to the interval [x, y] (signed)
301 * - n must be positive
302 * - x and y must be normalized modulo 2^n
303 * - x <= y must hold (2s'complement comparison)
304 * - the arrays are resized if necessary
305 */
bv_interval_set_s(bv_interval_t * intv,uint32_t * x,uint32_t * y,uint32_t n)306 void bv_interval_set_s(bv_interval_t *intv, uint32_t *x, uint32_t *y, uint32_t n) {
307 assert(n > 0 && bvconst_is_normalized(x, n) && bvconst_is_normalized(y, n) &&
308 bvconst_sle(x, y, n));
309
310 resize_bv_interval(intv, n);
311 bvconst_set(intv->low, intv->width, x);
312 bvconst_set(intv->high, intv->width, y);
313 }
314
315
316 /*
317 * Initialize to the trivial interval (unsigned)
318 * - n must be positive
319 * - low is set to 0b000..0
320 * - high is set to 0b111..1
321 */
bv_triv_interval_u(bv_interval_t * intv,uint32_t n)322 void bv_triv_interval_u(bv_interval_t *intv, uint32_t n) {
323 assert(n > 0);
324
325 resize_bv_interval(intv, n);
326 bvconst_clear(intv->low, intv->width);
327 bvconst_set_minus_one(intv->high, intv->width);
328 bvconst_normalize(intv->high, n);
329 }
330
331
332 /*
333 * Initialize to the trivial interval (signed)
334 * - n must be positive
335 * - low is set to 0b100..0
336 * - high is set to 0b0111..1
337 */
bv_triv_interval_s(bv_interval_t * intv,uint32_t n)338 void bv_triv_interval_s(bv_interval_t *intv, uint32_t n) {
339 assert(n > 0);
340
341 resize_bv_interval(intv, n);
342 bvconst_set_min_signed(intv->low, n);
343 bvconst_set_max_signed(intv->high, n);
344 }
345
346
347 /*
348 * Compute the interval that encloses the set S = [a.low, a.high] + [l, u]
349 * - n = bitsize
350 * - l and u must be normalized modulo 2^n
351 * - a must also be normalized and have nbits = n
352 */
bv_interval_add_u_core(bv_interval_t * a,uint32_t * l,uint32_t * u,uint32_t n)353 static void bv_interval_add_u_core(bv_interval_t *a, uint32_t *l, uint32_t *u, uint32_t n) {
354 uint32_t w;
355
356 assert(n > 0 && n == a->nbits);
357 assert(bv_interval_is_normalized(a) && bvconst_le(a->low, a->high, n));
358 assert(bvconst_is_normalized(l, n) && bvconst_is_normalized(u, n) && bvconst_le(l, u, n));
359
360 w = a->width;
361 assert(w == (n + 31) >> 5);
362
363 bvconst_add(a->low, w, l);
364 bvconst_add(a->high, w, u);
365 bvconst_normalize(a->low, n);
366 bvconst_normalize(a->high, n);
367
368 if (bvconst_lt(a->high, u, n) && bvconst_ge(a->low, l, n)) {
369 /*
370 * Overflow in a->high, no overflow in a->low so we have
371 * (a->low + l) < 2^n <= (a->high + u).
372 * The enclosing interval is [0b000..., 0b111...]
373 */
374 bvconst_clear(a->low, w);
375 bvconst_set_minus_one(a->high, w);
376 bvconst_normalize(a->high, n);
377 }
378
379 assert(bv_interval_is_normalized(a) && bvconst_le(a->low, a->high, n));
380 }
381
382
383
384 /*
385 * Check for overflow/underflow in a := a0 + b
386 * - sa = sign of a0 before the operation
387 * - n = number of bits in a and b
388 * - overflow: if (a0 >= 0) and (b >= 0) and (a < 0)
389 * - underflow: if (a0 < 0) and (b < 0) and (a >= 0)
390 */
add_overflow(uint32_t * a,uint32_t * b,bool sa,uint32_t n)391 static inline bool add_overflow(uint32_t *a, uint32_t *b, bool sa, uint32_t n) {
392 // sign bit of a0 = 0, sign bit of b = 0, sign bit of a = 1
393 return !sa & !bvconst_tst_bit(b, n-1) & bvconst_tst_bit(a, n-1);
394 }
395
add_underflow(uint32_t * a,uint32_t * b,bool sa,uint32_t n)396 static inline bool add_underflow(uint32_t *a, uint32_t *b, bool sa, uint32_t n) {
397 // sign bit of a0 = 1, sign bit of b = 1, sign bit of a = 0
398 return sa & bvconst_tst_bit(b, n-1) & !bvconst_tst_bit(a, n-1);
399 }
400
401
402 /*
403 * Sum of a and [l, n] for signed intervals
404 */
bv_interval_add_s_core(bv_interval_t * a,uint32_t * l,uint32_t * u,uint32_t n)405 static void bv_interval_add_s_core(bv_interval_t *a, uint32_t *l, uint32_t *u, uint32_t n) {
406 uint32_t w;
407 bool s_low, s_high;
408
409 assert(n > 0 && n == a->nbits);
410 assert(bv_interval_is_normalized(a) && bvconst_sle(a->low, a->high, n));
411 assert(bvconst_is_normalized(l, n) && bvconst_is_normalized(u, n) && bvconst_sle(l, u, n));
412
413 w = a->width;
414 assert(w == (n + 31) >> 5);
415
416 /*
417 * for overflow/underflow detection, store the sign of a->low and a->high
418 */
419 s_low = bvconst_tst_bit(a->low, n-1);
420 s_high = bvconst_tst_bit(a->high, n-1);
421
422 bvconst_add(a->low, w, l);
423 bvconst_add(a->high, w, u);
424 bvconst_normalize(a->low, n);
425 bvconst_normalize(a->high, n);
426
427 if ((add_underflow(a->low, l, s_low, n) && !add_underflow(a->high, u, s_high, n))
428 || (add_overflow(a->high, u, s_high, n) && !add_overflow(a->low, l, s_low, n))) {
429 bvconst_set_min_signed(a->low, n);
430 bvconst_set_max_signed(a->high, n);
431 }
432
433 assert(bv_interval_is_normalized(a) && bvconst_sle(a->low, a->high, n));
434 }
435
436
437
438
439
440 /*
441 * Compute the enclosing interval for a - [l, u] (unsigned intervals)
442 */
bv_interval_sub_u_core(bv_interval_t * a,uint32_t * l,uint32_t * u,uint32_t n)443 static void bv_interval_sub_u_core(bv_interval_t *a, uint32_t *l, uint32_t *u, uint32_t n) {
444 uint32_t w;
445
446 assert(n > 0 && n == a->nbits);
447 assert(bv_interval_is_normalized(a) && bvconst_le(a->low, a->high, n));
448 assert(bvconst_is_normalized(l, n) && bvconst_is_normalized(u, n) && bvconst_le(l, u, n));
449
450 w = a->width;
451 assert(w == (n + 31) >> 5);
452
453 if (bvconst_lt(a->low, u, n) && bvconst_ge(a->high, l, n)) {
454 /*
455 * (a->low - u) will underflow
456 * (a->high - l) will not underflow
457 * so the enclosing interval is [0b000..., 0b111...]
458 */
459 bvconst_clear(a->low, w);
460 bvconst_set_minus_one(a->high, w);
461 bvconst_normalize(a->high, n);
462 } else {
463 bvconst_sub(a->low, w, u); // a.low := a.low - u
464 bvconst_sub(a->high, w, l); // a,high := a.high - l
465 bvconst_normalize(a->low, n);
466 bvconst_normalize(a->high, n);
467
468 }
469
470 assert(bv_interval_is_normalized(a) && bvconst_le(a->low, a->high, n));
471 }
472
473
474
475
476 /*
477 * Check for overflow/underflow in a := a0 - b
478 * - sa = sign of a0 before the operation
479 * - n = number of bits in a and b
480 * - overflow: if (a0 >= 0) and (b < 0) and (a < 0)
481 * - underflow: if (a0 < 0) and (b >= 0) and (a >= 0)
482 */
sub_overflow(uint32_t * a,uint32_t * b,bool sa,uint32_t n)483 static inline bool sub_overflow(uint32_t *a, uint32_t *b, bool sa, uint32_t n) {
484 // sign bit of a0 = 0, sign bit of b = 1, sign bit of a = 1
485 return !sa & bvconst_tst_bit(b, n-1) & bvconst_tst_bit(a, n-1);
486 }
487
sub_underflow(uint32_t * a,uint32_t * b,bool sa,uint32_t n)488 static inline bool sub_underflow(uint32_t *a, uint32_t *b, bool sa, uint32_t n) {
489 // sign bit of a0 = 1, sign bit of b = 0, sign bit of a = 0
490 return sa & !bvconst_tst_bit(b, n-1) & !bvconst_tst_bit(a, n-1);
491 }
492
493
494 /*
495 * Sum of a and [l, n] for signed intervals
496 */
bv_interval_sub_s_core(bv_interval_t * a,uint32_t * l,uint32_t * u,uint32_t n)497 static void bv_interval_sub_s_core(bv_interval_t *a, uint32_t *l, uint32_t *u, uint32_t n) {
498 uint32_t w;
499 bool s_low, s_high;
500
501 assert(n > 0 && n == a->nbits);
502 assert(bv_interval_is_normalized(a) && bvconst_sle(a->low, a->high, n));
503 assert(bvconst_is_normalized(l, n) && bvconst_is_normalized(u, n) && bvconst_sle(l, u, n));
504
505 w = a->width;
506 assert(w == (n + 31) >> 5);
507
508 /*
509 * for overflow/underflow detection, store the sign of a->low and a->high
510 */
511 s_low = bvconst_tst_bit(a->low, n-1);
512 s_high = bvconst_tst_bit(a->high, n-1);
513
514 bvconst_sub(a->low, w, u); // a.low = a.low - u
515 bvconst_sub(a->high, w, l); // a.high = a.high - l
516 bvconst_normalize(a->low, n);
517 bvconst_normalize(a->high, n);
518
519 if ((sub_underflow(a->low, u, s_low, n) && !sub_underflow(a->high, l, s_high, n))
520 || (sub_overflow(a->high, l, s_high, n) && !sub_overflow(a->low, u, s_low, n))) {
521 bvconst_set_min_signed(a->low, n);
522 bvconst_set_max_signed(a->high, n);
523 }
524
525 assert(bv_interval_is_normalized(a) && bvconst_sle(a->low, a->high, n));
526 }
527
528
529
bv_interval_add_u(bv_interval_t * a,bv_interval_t * b)530 void bv_interval_add_u(bv_interval_t *a, bv_interval_t *b) {
531 bv_interval_add_u_core(a, b->low, b->high, b->nbits);
532 }
533
bv_interval_add_s(bv_interval_t * a,bv_interval_t * b)534 void bv_interval_add_s(bv_interval_t *a, bv_interval_t *b) {
535 bv_interval_add_s_core(a, b->low, b->high, b->nbits);
536 }
537
538
bv_interval_sub_u(bv_interval_t * a,bv_interval_t * b)539 void bv_interval_sub_u(bv_interval_t *a, bv_interval_t *b) {
540 bv_interval_sub_u_core(a, b->low, b->high, b->nbits);
541 }
542
bv_interval_sub_s(bv_interval_t * a,bv_interval_t * b)543 void bv_interval_sub_s(bv_interval_t *a, bv_interval_t *b) {
544 bv_interval_sub_s_core(a, b->low, b->high, b->nbits);
545 }
546
547
548
549
550
551 /*
552 * Overapproximation of [a.low + c * b.low, a.high + c * b.high] modulo 2^n
553 * - a and b must have the same bitsize and be normalized
554 * - c must be normalized modulo 2^n too
555 * - the result is stored in a
556 * Unsigned version
557 *
558 * The extra argument aux must be an initialized aux_buffer structure. It's used for internal
559 * computations if needed.
560 */
bv_interval_addmul_u(bv_interval_t * a,bv_interval_t * b,uint32_t * c,bv_aux_buffers_t * aux)561 void bv_interval_addmul_u(bv_interval_t *a, bv_interval_t *b, uint32_t *c, bv_aux_buffers_t *aux) {
562 uint32_t *b_low, *b_high;
563 uint32_t n, w;
564
565 b_low = b->low;
566 b_high = b->high;
567 n = b->nbits;
568 w = b->width;
569
570 assert(bvconst_is_normalized(c, n));
571
572 if (bvconst_is_one(c, w)) {
573 bv_interval_add_u_core(a, b_low, b_high, n);
574 } else if (bvconst_is_minus_one(c, n)) {
575 bv_interval_sub_u_core(a, b_low, b_high, n);
576 } else {
577 bv_aux_buffers_set_size(aux, 2 * w); // make the buffers large enough
578
579 if (!bvconst_tst_bit(c, n-1)) {
580 // c is less than 2^(n-1)
581 bv_aux_addmul_u(aux, a->high, b_high, c, n);
582 bv_aux_swap_ab(aux);
583 bv_aux_addmul_u(aux, a->low, b_low, c, n);
584 bv_aux_shift_a_to_c(aux, n);
585 bv_aux_shift_b_to_d(aux, n);
586
587 /*
588 * Let L = a->low + c * b->low and H = a->high + c * b->high.
589 * At this point we have:
590 * - remainder of L/2^n in aux->buffer_a
591 * - remainder of H/2^n in aux->buffer_b
592 * - quotient of L/2^n in aux->buffer_c
593 * - quotient of H/2^n in aux->buffer_d
594 *
595 * If the two quotients are equal, then we can use the
596 * two remainders as bounds. Otherwise, we return the
597 * trivial interval.
598 */
599 if (bvconst_eq(aux->buffer_c, aux->buffer_d, w)) {
600 bvconst_set(a->low, w, aux->buffer_a);
601 bvconst_set(a->high, w, aux->buffer_b);
602 } else {
603 bvconst_clear(a->low, w);
604 bvconst_set_minus_one(a->high, w);
605 bvconst_normalize(a->high, n);
606 }
607
608 } else {
609 // c is more than 2^(n-1), we use c' = -c modulo 2^n
610 bvconst_negate(c, w);
611 bvconst_normalize(c, n);
612
613 bv_aux_submul_u(aux, a->high, b_low, c, n);
614 bv_aux_swap_ab(aux);
615 bv_aux_submul_u(aux, a->low, b_high, c, n);
616 bv_aux_shift_a_to_c(aux, n);
617 bv_aux_shift_b_to_d(aux, n);
618
619 /*
620 * Let L = a->low - c' * b->high and H = a->high - c' * b->low.
621 * At this point we have:
622 * - remainder of L/2^n in aux->buffer_a
623 * - remainder of H/2^n in aux->buffer_b
624 * - quotient of L/2^n in aux->buffer_c
625 * - quotient of H/2^n in aux->buffer_d
626 */
627 if (bvconst_eq(aux->buffer_c, aux->buffer_d, w)) {
628 bvconst_set(a->low, w, aux->buffer_a);
629 bvconst_set(a->high, w, aux->buffer_b);
630 } else {
631 bvconst_clear(a->low, w);
632 bvconst_set_minus_one(a->high, w);
633 bvconst_normalize(a->high, n);
634 }
635
636 // restore c's value
637 bvconst_negate(c, w);
638 bvconst_normalize(c, n);
639 }
640
641 assert(bv_interval_is_normalized(a) && bvconst_le(a->low, a->high, n));
642 }
643 }
644
645
646
647 /*
648 * Overapproximation of [a.low + c * b.low, a.high + c * b.high] modulo 2^n
649 * - a and b must have the same bitsize and be normalized
650 * - c must be normalized modulo 2^n too
651 * - the result is stored in a
652 * Signed version.
653 *
654 * The extra argument aux must be an initialized aux_buffer structure. It's used for internal
655 * computations if needed.
656 */
bv_interval_addmul_s(bv_interval_t * a,bv_interval_t * b,uint32_t * c,bv_aux_buffers_t * aux)657 void bv_interval_addmul_s(bv_interval_t *a, bv_interval_t *b, uint32_t *c, bv_aux_buffers_t *aux) {
658 uint32_t *b_low, *b_high;
659 uint32_t n, w;
660
661 b_low = b->low;
662 b_high = b->high;
663 n = b->nbits;
664 w = b->width;
665
666 assert(bvconst_is_normalized(c, n));
667
668 if (bvconst_is_one(c, w)) {
669 bv_interval_add_s_core(a, b_low, b_high, n);
670 } else if (bvconst_is_minus_one(c, n)) {
671 bv_interval_sub_s_core(a, b_low, b_high, n);
672 } else {
673 bv_aux_buffers_set_size(aux, 2 * w); // make the buffers large enough
674
675 if (!bvconst_tst_bit(c, n-1)) {
676 // c is non-negative
677 bv_aux_addmul_s(aux, a->high, b_high, c, n);
678 bv_aux_swap_ab(aux);
679 bv_aux_addmul_s(aux, a->low, b_low, c, n);
680 bv_aux_shift_a_to_c(aux, n);
681 bv_aux_shift_b_to_d(aux, n);
682
683 /*
684 * Here we have:
685 * remainder of (a->low + c * b->low) divided by 2^n in buffer_a
686 * remainder of (a->high + c * b->high) divided by 2^n in buffer_b
687 * quotient of (a->low + c * b->low) divided by 2^n in buffer_c
688 * quotient of (a->high + c * b->high) divided by 2^n in buffer_d
689 */
690 } else {
691 // c is negative
692 bv_aux_addmul_s(aux, a->high, b_low, c, n);
693 bv_aux_swap_ab(aux);
694 bv_aux_addmul_s(aux, a->low, b_high, c, n);
695 bv_aux_shift_a_to_c(aux, n);
696 bv_aux_shift_b_to_d(aux, n);
697
698 /*
699 * Here we have:
700 * remainder of (a->low + c * b->low) divided by 2^n in buffer_a
701 * remainder of (a->high + c * b->high) divided by 2^n in buffer_b
702 * quotient of (a->low + c * b->low) divided by 2^n in buffer_c
703 * quotient of (a->high + c * b->high) divided by 2^n in buffer_d
704 */
705 }
706
707 if (bvconst_eq(aux->buffer_c, aux->buffer_d, w) && bvconst_sle(aux->buffer_a, aux->buffer_b, n)) {
708 // equal quotients and buffer_a <= buffer_b
709 bvconst_set(a->low, w, aux->buffer_a);
710 bvconst_set(a->high, w, aux->buffer_b);
711 } else {
712 bvconst_add_one(aux->buffer_c, w);
713 if (bvconst_eq(aux->buffer_c, aux->buffer_d, w) &&
714 bvconst_tst_bit(aux->buffer_a, n-1) && !bvconst_tst_bit(aux->buffer_b, n-1)) {
715 // quotient for low = quotient for high -1
716 // remainder for low is negative
717 // remainder for high is positive
718 bvconst_set(a->low, w, aux->buffer_a);
719 bvconst_set(a->high, w, aux->buffer_b);
720 } else {
721 // the full interval is larger than 2^n
722 bvconst_set_min_signed(a->low, n);
723 bvconst_set_max_signed(a->high, n);
724 }
725 }
726 }
727 }
728
729
730
731