Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_core/src/count.rs

6.1 KiB, 16 runs

created by r1870400018:74, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1use crate::{
2 prelude::*,
3 int::{
4 Bound,
5 One,
6 Zero,
7 },
8};
9
10use std::{
11 fmt,
12 ops::{
13 Add,
14 Div,
15 Mul,
16 Sub,
17 },
18};
19
20
21#[derive(Clone, Debug, Default)]
22pub struct ErrorWhen {
23 cnt: usize,
24 lim: usize,
25}
26
27impl ErrorWhen {
28 pub fn new(lim: usize) -> Self {
29 Self {
30 cnt: 0,
31 lim,
32 }
33 }
34
35 pub fn inc(&mut self) -> Outcome<()> {
36 if self.cnt == self.lim.saturating_sub(1) {
37 Err(err!(
38 "Counter reached limit of {}.", self.lim;
39 LimitReached))
40 } else {
41 self.cnt += 1;
42 Ok(())
43 }
44 }
45}
46
47#[derive(Clone, Debug, Default)]
48pub struct TrueWhen {
49 cnt: usize,
50 lim: usize,
51}
52
53impl TrueWhen {
54 pub fn new(lim: usize) -> Self {
55 Self {
56 cnt: 0,
57 lim,
58 }
59 }
60
61 pub fn inc(&mut self) -> bool {
62 if self.cnt == self.lim.saturating_sub(1) {
63 true
64 } else {
65 self.cnt += 1;
66 false
67 }
68 }
69}
70
71/// A numerical iterator that provides the `next` and `prev` values in `delta` increments within a
72/// range `[start, end]`.
73#[derive(Clone, Debug)]
74pub struct Counter<
75 T: Clone
76 + Copy
77 + fmt::Debug
78 + fmt::Display
79 + PartialOrd
80 + Ord
81 + Add<Output = T>
82 + Sub<Output = T>
83 + Mul<Output = T>
84 + Div<Output = T>
85 + Bound
86 + One
87 + Zero
88> {
89 start: T,
90 end: T,
91 delta: T,
92 current: T,
93}
94
95impl<
96 T: Clone
97 + Copy
98 + fmt::Debug
99 + fmt::Display
100 + PartialOrd
101 + Ord
102 + Add<Output = T>
103 + Sub<Output = T>
104 + Mul<Output = T>
105 + Div<Output = T>
106 + Bound
107 + One
108 + Zero
109>
110 Default for Counter<T>
111{
112 fn default() -> Self {
113 Self {
114 start: T::zero(),
115 end: T::max_size(),
116 delta: T::one(),
117 current: T::zero(),
118 }
119 }
120}
121
122impl<
123 T: Clone
124 + Copy
125 + fmt::Debug
126 + fmt::Display
127 + PartialOrd
128 + Ord
129 + Add<Output = T>
130 + Sub<Output = T>
131 + Mul<Output = T>
132 + Div<Output = T>
133 + Bound
134 + One
135 + Zero
136>
137 Counter<T>
138{
139 pub fn new(
140 start: T,
141 end: T,
142 delta: T,
143 )
144 -> Outcome<Self>
145 {
146 if start >= end {
147 return Err(err!(
148 "The end {} should be after the start {}.", end, start;
149 Input, Invalid, Order, Integer));
150 }
151 let d = (end - start) / delta;
152 if start + d * delta != end {
153 return Err(err!(
154 "The range [{}, {}] is not divisible by the given delta {}.",
155 start, end, delta;
156 Input, Invalid, Divisibility, Integer));
157 }
158 Ok(Self {
159 start,
160 end,
161 delta,
162 current: start,
163 })
164 }
165
166 pub fn start(&self) -> T { self.start }
167 pub fn end(&self) -> T { self.end }
168 pub fn delta(&self) -> T { self.delta }
169 pub fn current(&self) -> T { self.current }
170
171 pub fn next(&mut self) -> Option<T> {
172 if self.current <= self.end - self.delta {
173 self.current = self.current + self.delta;
174 Some(self.current)
175 } else {
176 None
177 }
178 }
179
180 pub fn prev(&mut self) -> Option<T> {
181 if self.current >= self.start + self.delta {
182 self.current = self.current - self.delta;
183 Some(self.current)
184 } else {
185 None
186 }
187 }
188}
189
190/// A numerical iterator that provides the `next` and `prev` values in `delta` increments within a
191/// range `[start, end]`, and when the end points are reached, cycles back.
192#[derive(Clone, Debug)]
193pub struct CycleCounter<
194 T: Clone
195 + Copy
196 + fmt::Debug
197 + fmt::Display
198 + PartialOrd
199 + Ord
200 + Add<Output = T>
201 + Sub<Output = T>
202 + Mul<Output = T>
203 + Div<Output = T>
204 + Bound
205 + One
206 + Zero
207> {
208 start: T,
209 end: T,
210 delta: T,
211 current: T,
212}
213
214impl<
215 T: Clone
216 + Copy
217 + fmt::Debug
218 + fmt::Display
219 + PartialOrd
220 + Ord
221 + Add<Output = T>
222 + Sub<Output = T>
223 + Mul<Output = T>
224 + Div<Output = T>
225 + Bound
226 + One
227 + Zero
228>
229 Default for CycleCounter<T>
230{
231 fn default() -> Self {
232 Self {
233 start: T::zero(),
234 end: T::max_size(),
235 delta: T::one(),
236 current: T::zero(),
237 }
238 }
239}
240
241impl<
242 T: Clone
243 + Copy
244 + fmt::Debug
245 + fmt::Display
246 + PartialOrd
247 + Ord
248 + Add<Output = T>
249 + Sub<Output = T>
250 + Mul<Output = T>
251 + Div<Output = T>
252 + Bound
253 + One
254 + Zero
255>
256 CycleCounter<T>
257{
258 pub fn new(
259 start: T,
260 end: T,
261 delta: T,
262 )
263 -> Outcome<Self>
264 {
265 if start >= end {
266 return Err(err!(
267 "The end {} should be after the start {}.", end, start;
268 Input, Invalid, Order, Integer));
269 }
270 let d = (end - start) / delta;
271 if start + d * delta != end {
272 return Err(err!(
273 "The range [{}, {}] is not divisible by the given delta {}.",
274 start, end, delta;
275 Input, Invalid, Divisibility, Integer));
276 }
277 Ok(Self {
278 start,
279 end,
280 delta,
281 current: start,
282 })
283 }
284
285 pub fn start(&self) -> T { self.start }
286 pub fn end(&self) -> T { self.end }
287 pub fn delta(&self) -> T { self.delta }
288 pub fn current(&self) -> T { self.current }
289
290 pub fn next(&mut self) -> T {
291 if self.current <= self.end - self.delta {
292 self.current = self.current + self.delta;
293 self.current
294 } else {
295 self.current = self.start;
296 self.current
297 }
298 }
299
300 pub fn prev(&mut self) -> T {
301 if self.current >= self.start + self.delta {
302 self.current = self.current - self.delta;
303 self.current
304 } else {
305 self.current = self.end;
306 self.current
307 }
308 }
309}