genetic_algorithm/
allele.rs1use impl_trait_for_tuples::impl_for_tuples;
3use rand::distributions::uniform::SampleUniform;
4use std::hash::{Hash, Hasher};
5use std::ops::{Add, AddAssign, Sub, SubAssign};
6
7pub trait Allele: Clone + Copy + Send + Sync + std::fmt::Debug {
9 fn hash_slice(slice: &[Self], hasher: &mut impl Hasher)
13 where
14 Self: Sized;
15}
16
17#[macro_export]
20macro_rules! impl_allele{
21 ($($t:ty),*) => {
22 $(
23 impl $crate::allele::Allele for $t {
24 fn hash_slice(slice: &[Self], hasher: &mut impl ::std::hash::Hasher) {
25 ::std::hash::Hash::hash(slice, hasher);
26 }
27 }
28 )*
29 }
30}
31
32impl_allele!(bool, char, i128, i16, i32, i64, i8, isize, u128, u16, u32, u64, u8, usize);
33impl Allele for f32 {
34 fn hash_slice(slice: &[Self], hasher: &mut impl Hasher) {
35 let bytes: &[u8] = bytemuck::cast_slice(slice);
36 bytes.hash(hasher);
37 }
38}
39impl Allele for f64 {
40 fn hash_slice(slice: &[Self], hasher: &mut impl Hasher) {
41 let bytes: &[u8] = bytemuck::cast_slice(slice);
42 bytes.hash(hasher);
43 }
44}
45
46#[impl_for_tuples(0, 12)]
48impl Allele for Tuple {
49 for_tuples!( where #( Tuple: Allele + Hash ),* );
50
51 fn hash_slice(slice: &[Self], hasher: &mut impl Hasher) {
52 slice.hash(hasher);
53 }
54}
55
56pub trait RangeAllele:
59 Allele
60 + Add<Output = Self>
61 + Sub<Output = Self>
62 + AddAssign
63 + SubAssign
64 + std::cmp::PartialOrd
67 + Default
68 + bytemuck::NoUninit
69 + SampleUniform
70{
71 fn smallest_increment() -> Self;
73
74 fn zero() -> Self;
76
77 fn one() -> Self;
79
80 fn floor(&self) -> Self;
82
83 fn clamped_add(current_value: Self, delta: Self, max_value: Self) -> Self;
85 fn clamped_sub(current_value: Self, delta: Self, min_value: Self) -> Self;
86 fn min(a: Self, b: Self) -> Self {
87 if a < b { a } else { b }
88 }
89}
90
91impl RangeAllele for f32 {
92 fn smallest_increment() -> Self {
93 f32::EPSILON
94 }
95 fn zero() -> Self {
96 0.0
97 }
98 fn one() -> Self {
99 1.0
100 }
101 fn floor(&self) -> Self {
102 f32::floor(*self)
103 }
104 fn clamped_add(current_value: Self, delta: Self, max_value: Self) -> Self {
106 let new_value = current_value + delta;
107 if new_value > max_value {
108 max_value
109 } else {
110 new_value
111 }
112 }
113 fn clamped_sub(current_value: Self, delta: Self, min_value: Self) -> Self {
115 let new_value = current_value - delta;
116 if new_value < min_value {
117 min_value
118 } else {
119 new_value
120 }
121 }
122}
123impl RangeAllele for f64 {
124 fn smallest_increment() -> Self {
125 f64::EPSILON
126 }
127 fn zero() -> Self {
128 0.0
129 }
130 fn one() -> Self {
131 1.0
132 }
133 fn floor(&self) -> Self {
134 f64::floor(*self)
135 }
136 fn clamped_add(current_value: Self, delta: Self, max_value: Self) -> Self {
138 let new_value = current_value + delta;
139 if new_value > max_value {
140 max_value
141 } else {
142 new_value
143 }
144 }
145 fn clamped_sub(current_value: Self, delta: Self, min_value: Self) -> Self {
147 let new_value = current_value - delta;
148 if new_value < min_value {
149 min_value
150 } else {
151 new_value
152 }
153 }
154}
155impl RangeAllele for i8 {
156 fn smallest_increment() -> Self {
157 1
158 }
159 fn zero() -> Self {
160 0
161 }
162 fn one() -> Self {
163 1
164 }
165 fn floor(&self) -> Self {
166 *self
167 }
168 fn clamped_add(current_value: Self, delta: Self, max_value: Self) -> Self {
169 let new_value = current_value.saturating_add(delta);
170 if new_value > max_value {
171 max_value
172 } else {
173 new_value
174 }
175 }
176 fn clamped_sub(current_value: Self, delta: Self, min_value: Self) -> Self {
177 let new_value = current_value.saturating_sub(delta);
178 if new_value < min_value {
179 min_value
180 } else {
181 new_value
182 }
183 }
184}
185impl RangeAllele for i16 {
186 fn smallest_increment() -> Self {
187 1
188 }
189 fn zero() -> Self {
190 0
191 }
192 fn one() -> Self {
193 1
194 }
195 fn floor(&self) -> Self {
196 *self
197 }
198 fn clamped_add(current_value: Self, delta: Self, max_value: Self) -> Self {
199 let new_value = current_value.saturating_add(delta);
200 if new_value > max_value {
201 max_value
202 } else {
203 new_value
204 }
205 }
206 fn clamped_sub(current_value: Self, delta: Self, min_value: Self) -> Self {
207 let new_value = current_value.saturating_sub(delta);
208 if new_value < min_value {
209 min_value
210 } else {
211 new_value
212 }
213 }
214}
215impl RangeAllele for i32 {
216 fn smallest_increment() -> Self {
217 1
218 }
219 fn zero() -> Self {
220 0
221 }
222 fn one() -> Self {
223 1
224 }
225 fn floor(&self) -> Self {
226 *self
227 }
228 fn clamped_add(current_value: Self, delta: Self, max_value: Self) -> Self {
229 let new_value = current_value.saturating_add(delta);
230 if new_value > max_value {
231 max_value
232 } else {
233 new_value
234 }
235 }
236 fn clamped_sub(current_value: Self, delta: Self, min_value: Self) -> Self {
237 let new_value = current_value.saturating_sub(delta);
238 if new_value < min_value {
239 min_value
240 } else {
241 new_value
242 }
243 }
244}
245impl RangeAllele for u8 {
246 fn smallest_increment() -> Self {
247 1
248 }
249 fn zero() -> Self {
250 0
251 }
252 fn one() -> Self {
253 1
254 }
255 fn floor(&self) -> Self {
256 *self
257 }
258 fn clamped_add(current_value: Self, delta: Self, max_value: Self) -> Self {
259 let new_value = current_value.saturating_add(delta);
260 if new_value > max_value {
261 max_value
262 } else {
263 new_value
264 }
265 }
266 fn clamped_sub(current_value: Self, delta: Self, min_value: Self) -> Self {
267 let new_value = current_value.saturating_sub(delta);
268 if new_value < min_value {
269 min_value
270 } else {
271 new_value
272 }
273 }
274}
275impl RangeAllele for u16 {
276 fn smallest_increment() -> Self {
277 1
278 }
279 fn zero() -> Self {
280 0
281 }
282 fn one() -> Self {
283 1
284 }
285 fn floor(&self) -> Self {
286 *self
287 }
288 fn clamped_add(current_value: Self, delta: Self, max_value: Self) -> Self {
289 let new_value = current_value.saturating_add(delta);
290 if new_value > max_value {
291 max_value
292 } else {
293 new_value
294 }
295 }
296 fn clamped_sub(current_value: Self, delta: Self, min_value: Self) -> Self {
297 let new_value = current_value.saturating_sub(delta);
298 if new_value < min_value {
299 min_value
300 } else {
301 new_value
302 }
303 }
304}
305impl RangeAllele for u32 {
306 fn smallest_increment() -> Self {
307 1
308 }
309 fn zero() -> Self {
310 0
311 }
312 fn one() -> Self {
313 1
314 }
315 fn floor(&self) -> Self {
316 *self
317 }
318 fn clamped_add(current_value: Self, delta: Self, max_value: Self) -> Self {
319 let new_value = current_value.saturating_add(delta);
320 if new_value > max_value {
321 max_value
322 } else {
323 new_value
324 }
325 }
326 fn clamped_sub(current_value: Self, delta: Self, min_value: Self) -> Self {
327 let new_value = current_value.saturating_sub(delta);
328 if new_value < min_value {
329 min_value
330 } else {
331 new_value
332 }
333 }
334}