Struct aws_smt_strings::loop_ranges::LoopRange
source · pub struct LoopRange(/* private fields */);
Expand description
Loop range
A loop range is either a finite interval [i, j] or an infinite interval [i, ..]
- A finite interval is represented as
LoopRange(i, Some(j))
where 0 <= i <= j - An infinite interval is represented as
LoopRange(i, None)
.
The integers i and j are stored as u32. Operations on loop ranges will panic if results cannot be stored using 32bit unsigned integers.
Implementations§
source§impl LoopRange
impl LoopRange
sourcepub fn is_infinite(&self) -> bool
pub fn is_infinite(&self) -> bool
Check whether this range is infinite
sourcepub fn includes(&self, other: &LoopRange) -> bool
pub fn includes(&self, other: &LoopRange) -> bool
Check inclusion
- return true if other is included in self.
sourcepub fn add(&self, other: &LoopRange) -> LoopRange
pub fn add(&self, other: &LoopRange) -> LoopRange
Add two ranges
The result is the union of both ranges.
This is used to rewrite (concat (loop L a b) (loop L c d))
to (loop L (add [a, b], [c, d]))
.
Panics
If an arithmetic overflow occurs, that is, the union of the two ranges cannot be represented using 32bit unsigned integers, this method will panic.
sourcepub fn scale(&self, k: u32) -> LoopRange
pub fn scale(&self, k: u32) -> LoopRange
Multiply by a constant k
- If the current range is a finite interval [i, j], return [k * i, k * j]
- If the current range is an infinite interval [i, +infinity] and k is not zero, return [k * i, +infinity]
- If k is zero, return [0, 0] even if the current range is infinite
This corresponds to adding [i, j] to itself k times.
This can be used to rewrite
(loop L i j)^k
= (loop L (k * i) (k * j))
Panics
If there’s an arithmetic overflow in k * i or k * j.
sourcepub fn mul(&self, other: &LoopRange) -> LoopRange
pub fn mul(&self, other: &LoopRange) -> LoopRange
Multiply two ranges
The product of the ranges [a, b] and [c, d] (where b or d may be +infinity) is the range [a * c, b * d]. The following rules handle multiplication with infinity:
- 0 * infinity = infinity * 0 = 0
- k * infinity = infinity * k = infinity if k is finite and non-zero
- infinity * infinity = infinity
Note:
The actual product of [a, b] and [c, d] is the set of integers P = { x * y | a <= x <= b and c <= y <= d }.
The interval [a * c, b * d] is an over approximation of P, since P may not be an interval.
For example: if [a, b] = [0, 1] and [c, d] = [3, 4] then P is { 0, 3, 4 } but [0, 1] * [3, 4] is [0, 4].
Method right_mul_is_exact can be used to check whether the product is exact.
Panics
If there’s an arithmetic overflow in the product computation, that is, the result cannot be stored using u32 integers, this method will panic.
sourcepub fn right_mul_is_exact(&self, other: &LoopRange) -> bool
pub fn right_mul_is_exact(&self, other: &LoopRange) -> bool
Check whether the product of two ranges is an interval.
Given a range r = [a, b] and s = [c, d], then
r.right_mul_is_exact(s)
returns true if the Union(k * [a, b]) for k in s is equal to [a, b] * [c, d].
If it is, we can rewrite (loop (loop L a b) c d)
to (loop L a * c b * d)
.
Note:
The product of two ranges is commutative but this method is not. For example:
-
Union(k * [0, +infinity], k in [2, 2]) = 2 * [0, +infinity] = [0, +infinity] so
(loop (loop L 0 +infinity) 2 2)
= (L*)^2 = L* -
Union(k * [2, 2], k in [0, +infinity]) = { 2 * k | k in [0, +infinity] } so
(loop (loop L 2 2) 0 +infinity)
= (L^2)* (not the same as L*)
Example
use aws_smt_strings::loop_ranges::*;
let r = LoopRange::point(2); // range [2, 2]
let s = LoopRange::star(); // range [0, +infinity]
assert!(s.right_mul_is_exact(&r)); // [0, +infinity] * [2, 2] is [0, +infinity] (exact)
assert!(!r.right_mul_is_exact(&s)); // [2, 2] * [0, +infinity] is not an interval