Ranges are finite numerical intervals, e.g. "all integers i such that (m <= i) and (i < n)". The high end bound is sometimes exclusive, (i < n), and
sometimes inclusive, (i <= n).
In Wuffs syntax, similar to Rust syntax, the exclusive range is m .. n and
the inclusive range is m ..= n. The conventional mathematical syntax is [m, n) or [m, n[ for exclusive and [m, n] for inclusive, but Wuffs is a
programming language, and programming language tools prefer brackets to always
be balanced.
In Wuffs' C form, the exclusive range is wuffs_base__range_ie_T and the
inclusive range is wuffs_base__range_ii_T. The ie means inclusive on the
low end, exclusive on the high end. The T is a numerical type like u32 or
u64.
Both of the ii and ie flavors are useful in practice: ii or m ..= n is
more convenient when computing interval
arithmetic, ie or m .. n is more
convenient when working with slices.
The ei and ee flavors also exist in theory, but aren't widely used. In
Wuffs, the low end is always inclusive.
The ie (half-open) flavor is recommended by Dijkstra's "Why numbering should
start at zero" and see
also a further discussion of half-open
intervals.
For example, with ie, the number of elements in "uint32_t values in the
half-open interval m .. n" is equal to max(0, n - m). Furthermore, that
number of elements (in one dimension, a length, in two dimensions, a width or
height) is itself representable as a uint32_t without overflow, again for
uint32_t values m and n. In the contrasting ii flavor, the size of the
closed interval 0 ..= ((1<<32) - 1) is 1<<32, which cannot be represented
as a uint32_t.
In Wuffs' C form, because of this potential overflow, the ie flavor has
length / width / height methods, but the ii flavor does not.
The ii (closed) flavor is useful when refining e.g. "the set of all
uint32_t values" to a contiguous subset: "uint32_t values in the closed
interval m ..= n", for uint32_t values m and n. An unrefined type (in
other words, the set of all uint32_t values) is not representable in the ie
flavor because if n equals ((1<<32) - 1) then (n + 1) will overflow.
It is valid for m >= n (for the ie case) or for m > n (for the ii
case), in which case the range is empty. There are multiple valid
representations of an empty range: (m=1, n=0) and (m=99, n=77) are
equivalent.
Rects are just the 2-dimensional form of (1-dimensional) ranges. For example,
wuffs_base__rect_ii_u32 is a rectangle on the integer grid, containing all
points (x, y) such that (min_incl_x <= x) and (x <= max_incl_x), and
likewise for y.
Once again, it is valid for min > max, and there are multiple valid
representations of an empty rectangle.
When rects are used in graphics, the X and Y axes increase right and down.