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