1/* @title: Range Macros */
2#pragma once
3#include <kassert.h>
4#define IN_RANGE(x, min, max) \
5 ({ \
6 (void) kassert((min) <= (max)); \
7 (x) >= (min) && (x) <= (max); \
8 })
9
10struct range {
11 uint64_t low;
12 uint64_t hi;
13};
14
15#define RANGE(min, max) \
16 ((struct range) {.low = (uint64_t) (min), .hi = (uint64_t) (max)})
17
18#define RANGE_DEFINE(type, name) \
19 struct { \
20 type low; \
21 type hi; \
22 } name
23
24#define RANGE_LEN(r) (((r).hi - (r).low) + 1)
25#define RANGE_CONTAINS(r, val) ((val) >= (r).low && (val) <= (r).hi)
26#define RANGE_OVERLAPS(r1, r2) ((r1).low <= (r2).hi && (r2).low <= (r1).hi)
27#define RANGE_VALID(r) ((r).low <= (r).hi)
28
29/* Cap r1's bounds to fit within r2, returning true if an intersection exists */
30#define RANGE_CLAMP(r1, r2, out_r) \
31 ((r1).low <= (r2).hi && (r2).low <= (r1).hi \
32 ? ((out_r).low = ((r1).low > (r2).low) ? (r1).low : (r2).low, \
33 (out_r).hi = ((r1).hi < (r2).hi) ? (r1).hi : (r2).hi, true) \
34 : false)
35
36/* Merge r1 and r2 into out_r if they overlap or touch */
37#define RANGE_MERGE(r1, r2, out_r) \
38 (((r1).low <= (r2).hi + 1) && ((r2).low <= (r1).hi + 1) \
39 ? ((out_r).low = ((r1).low < (r2).low) ? (r1).low : (r2).low, \
40 (out_r).hi = ((r1).hi > (r2).hi) ? (r1).hi : (r2).hi, true) \
41 : false)
42