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.