this repo has no description
1const std = @import("std");
2
3pub const IntervalU8 = Interval(u8);
4pub const IntervalU16 = Interval(u16);
5pub const IntervalU32 = Interval(u32);
6pub const IntervalU64 = Interval(u64);
7pub const IntervalUsize = Interval(usize);
8
9pub const IntervalI8 = Interval(i8);
10pub const IntervalI16 = Interval(i16);
11pub const IntervalI32 = Interval(i32);
12pub const IntervalI64 = Interval(i64);
13pub const IntervalIsize = Interval(isize);
14
15pub const IntervalF32 = Interval(f32);
16pub const IntervalF64 = Interval(f64);
17
18pub const IntervalIteratorType = enum {
19 inclusive,
20 exclusive,
21};
22
23pub fn Interval(comptime T: type) type {
24 if (@typeInfo(T) == .int) {
25 return IntInterval(T);
26 } else if (@typeInfo(T) == .float) {
27 return FloatInterval(T);
28 } else {
29 @compileError("Interval only supports Int and Float Types!");
30 }
31}
32
33fn IntInterval(comptime T: type) type {
34 return struct {
35 const Self = @This();
36
37 pub const empty: Self = .{ .min = std.math.inf(T), .max = -std.math.inf(T) };
38 pub const universe: Self = .{ .min = -std.math.inf(T), .max = std.math.inf(T) };
39
40 pub const Iterator = struct {
41 interval: Self,
42 current: T,
43
44 lower_boundry: IntervalIteratorType = .inclusive,
45 upper_boundry: IntervalIteratorType = .exclusive,
46
47 pub fn init(
48 interval: Self,
49 lower_boundry: IntervalIteratorType,
50 upper_boundry: IntervalIteratorType,
51 ) Iterator {
52 return .{
53 .interval = interval,
54 .current = if (lower_boundry == .inclusive) interval.min else interval.min + 1,
55 .lower_boundry = lower_boundry,
56 .upper_boundry = upper_boundry,
57 };
58 }
59
60 pub fn next(self: *Iterator) ?T {
61 self.current += 1;
62 if (self.current < self.interval.max or (self.current == self.interval.max and self.upper_boundry == .inclusive)) {
63 return self.current - 1;
64 } else return null;
65 }
66
67 pub fn nextInc(self: *Iterator) ?T {
68 self.current += 1;
69 return if (self.current <= self.interval.max) self.current - 1 else null;
70 }
71
72 pub fn nextExc(self: *Iterator) ?T {
73 self.current += 1;
74 return if (self.current < self.interval.max) self.current - 1 else null;
75 }
76 };
77
78 min: T,
79 max: T,
80
81 pub fn init(min: T, max: T) Interval {
82 return .{ .min = min, .max = max };
83 }
84
85 pub fn initI(a: Self, b: Self) Self {
86 return Self{ .min = @min(a.min, b.min), .max = @max(a.max, b.max) };
87 }
88
89 pub fn contains(self: *const Self, x: T) bool {
90 return self.min <= x and x <= self.max;
91 }
92
93 pub fn surrounds(self: *const Self, x: T) bool {
94 return self.min < x and x < self.max;
95 }
96
97 pub fn clamp(self: *const Self, x: T) T {
98 if (x < self.min) return self.min;
99 if (x > self.max) return self.max;
100 return x;
101 }
102
103 pub fn expand(self: *const Self, delta: T) Interval {
104 const padding = delta / 2;
105 return .{ .min = self.min - padding, .max = self.max + padding };
106 }
107
108 pub fn size(self: *const Self) T {
109 return self.max - self.min;
110 }
111
112 pub fn iter(self: *const Self) Iterator {
113 return Iterator{
114 .interval = self.*,
115 .current = self.min,
116 };
117 }
118 };
119}
120
121fn FloatInterval(comptime T: type) type {
122 return struct {
123 pub const empty: @This() = .{ .min = std.math.inf(T), .max = -std.math.inf(T) };
124 pub const universe: @This() = .{ .min = -std.math.inf(T), .max = std.math.inf(T) };
125
126 const Self = @This();
127
128 min: T,
129 max: T,
130
131 pub fn init(min: T, max: T) Self {
132 return Self{ .min = min, .max = max };
133 }
134
135 pub fn initI(a: Self, b: Self) Self {
136 return Self{ .min = @min(a.min, b.min), .max = @max(a.max, b.max) };
137 }
138
139 pub fn contains(self: *const Self, x: T) bool {
140 return self.min <= x and x <= self.max;
141 }
142
143 pub fn surrounds(self: *const Self, x: T) bool {
144 return self.min < x and x < self.max;
145 }
146
147 pub fn clamp(self: *const Self, x: T) T {
148 if (x < self.min) return self.min;
149 if (x > self.max) return self.max;
150 return x;
151 }
152
153 pub fn expand(self: *const Self, delta: T) Self {
154 const padding = delta / 2;
155 return .{ .min = self.min - padding, .max = self.max + padding };
156 }
157
158 pub fn size(self: *const Self) T {
159 return self.max - self.min;
160 }
161 };
162}