| 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 | |
| 10 | struct 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 | |