@@ -254,6 +254,13 @@ interval_abstract_valuet::interval_abstract_valuet(
254
254
{
255
255
}
256
256
257
+ interval_abstract_valuet::interval_abstract_valuet (
258
+ const exprt &lower,
259
+ const exprt &upper)
260
+ : interval_abstract_valuet(constant_interval_exprt(lower, upper))
261
+ {
262
+ }
263
+
257
264
interval_abstract_valuet::interval_abstract_valuet (
258
265
const exprt &e,
259
266
const abstract_environmentt &environment,
@@ -344,14 +351,34 @@ void interval_abstract_valuet::output(
344
351
}
345
352
}
346
353
347
- // / Merge another interval abstract object with this one
348
- // / \param other The abstract value object to merge with
349
- // / \param widen_mode: Indicates if this is a widening merge
350
- // / \return This if the other interval is subsumed by this,
351
- // / other if this is subsumed by other.
352
- // / Otherwise, a new interval abstract object
353
- // / with the smallest interval that subsumes both
354
- // / this and other
354
+ abstract_object_pointert widening_merge (
355
+ const constant_interval_exprt &lhs,
356
+ const constant_interval_exprt &rhs)
357
+ {
358
+ auto lower_bound =
359
+ constant_interval_exprt::get_min (lhs.get_lower (), rhs.get_lower ());
360
+ auto upper_bound =
361
+ constant_interval_exprt::get_max (lhs.get_upper (), rhs.get_upper ());
362
+ auto range = plus_exprt (
363
+ minus_exprt (upper_bound, lower_bound), from_integer (1 , lhs.type ()));
364
+
365
+ auto dummy_symbol_table = symbol_tablet{};
366
+ auto dummy_namespace = namespacet{dummy_symbol_table};
367
+
368
+ // should extend lower bound?
369
+ if (rhs.get_lower () < lhs.get_lower ())
370
+ lower_bound =
371
+ simplify_expr (minus_exprt (lower_bound, range), dummy_namespace);
372
+ // should extend upper bound?
373
+ if (lhs.get_upper () < rhs.get_upper ())
374
+ upper_bound =
375
+ simplify_expr (plus_exprt (upper_bound, range), dummy_namespace);
376
+
377
+ // new interval ...
378
+ auto new_interval = constant_interval_exprt (lower_bound, upper_bound);
379
+ return make_interval (new_interval);
380
+ }
381
+
355
382
abstract_object_pointert interval_abstract_valuet::merge_with_value (
356
383
const abstract_value_pointert &other,
357
384
const widen_modet &widen_mode) const
@@ -367,19 +394,17 @@ abstract_object_pointert interval_abstract_valuet::merge_with_value(
367
394
if (interval.contains (other_interval))
368
395
return shared_from_this ();
369
396
370
- return make_interval (constant_interval_exprt (
371
- constant_interval_exprt::get_min (
372
- interval.get_lower (), other_interval.get_lower ()),
373
- constant_interval_exprt::get_max (
374
- interval.get_upper (), other_interval.get_upper ())));
397
+ if (widen_mode == widen_modet::could_widen)
398
+ return widening_merge (interval, other_interval);
399
+
400
+ auto lower_bound = constant_interval_exprt::get_min (
401
+ interval.get_lower (), other_interval.get_lower ());
402
+ auto upper_bound = constant_interval_exprt::get_max (
403
+ interval.get_upper (), other_interval.get_upper ());
404
+
405
+ return make_interval (lower_bound, upper_bound);
375
406
}
376
407
377
- // / Meet another interval abstract object with this one
378
- // / \param other The interval abstract object to meet with
379
- // / \return This if the other interval subsumes this,
380
- // / other if this subsumes other.
381
- // / Otherwise, a new interval abstract object
382
- // / with the intersection interval (of this and other)
383
408
abstract_object_pointert interval_abstract_valuet::meet_with_value (
384
409
const abstract_value_pointert &other) const
385
410
{
0 commit comments