1use crate::phast::{conf::Conf, cyclic::{CyclicSet, GenericUsedValue, UsedValueSetLarge}, Weights};
2use super::SeedChooser;
3
4#[inline] fn self_collide(without_shift: &mut [usize]) -> bool {
5 without_shift.sort_unstable(); for i in 1..without_shift.len() {
7 if without_shift[i-1] == without_shift[i] { return true;
9 }
10 }
11 false
12}
13
14#[inline] fn shifts0<'k, 'c>(keys: &'k [u64], conf: &'c Conf) -> impl Iterator<Item = usize> + use<'k, 'c> {
15 keys.iter().map(|key| conf.f_shift0(*key))
16}
17
18#[inline] fn occupy_sum<const UVS: usize>(mut excluded: u64, used_values: &CyclicSet<UVS>, without_shift: &[usize], shift: u16) -> u64 {
19 for first in without_shift.iter() {
20 excluded |= used_values.get64(*first + shift as usize);
21 }
22 excluded
23}
24
25#[inline] fn mark_used<const UVS: usize>(used_values: &mut CyclicSet<UVS>, without_shift: &[usize], total_shift: u16) {
26 for first in without_shift {
27 used_values.add(*first + total_shift as usize);
28 }
29}
30
31#[derive(Clone, Copy, Default)]
38pub struct ShiftOnly;
39
40impl SeedChooser for ShiftOnly {
44 const FUNCTION2_THRESHOLD: usize = 8192;
45
46 type UsedValues = UsedValueSetLarge;
47
48 fn bucket_evaluator(&self, bits_per_seed: u8, slice_len: u16) -> Weights {
49 Weights(
50 if slice_len <= 256 { match (bits_per_seed, slice_len) {
51 (..=6, ..=128) => [-98439, 68040, 81130, 86896, 91188, 93897, 296481], (..=6, _) => [-81980, 50520, 90817, 106897, 116472, 123937, 287280], (_, ..=128) => [-173163, 58917, 73926, 83423, 88222, 92168, 206758], (..=7, _) => [-85977, 81531, 98837, 107586, 113333, 117710, 120656], (_, _) => [-85787, 84108, 99553, 107291, 112859, 117377, 119965], }} else { match (bits_per_seed, slice_len) {
57 (..=7, ..=512) => [-95834, 38499, 103035, 124756, 137603, 147839, 155448], (_, ..=512) => [-68137, 80516, 110189, 123629, 132794, 140850, 145685], (..=8, ..=1024) => [-49776, 28610, 120514, 154976, 177328, 193499, 204936], (..=8, ..=2048) => [-14014, -11926, 63698, 144877, 194056, 353593, 360338], (9, ..=1024) => [-60439, 49207, 121850, 149181, 166713, 179181, 187815], (9, ..=2048) => [48168, 48328, 132443, 197796, 234543, 260358, 279164], (10, ..=1024) => [-4759, 9930, 87924, 125082, 143308, 165460, 165095], (10, ..=2048) => [-3419, 8042, 98860, 145429, 176433, 198538, 214441], (_, ..=1024) => [-1560, 25555, 96323, 156791, 189688, 201315, 198828], (11, ..=2048) => [-294, 2300, 161956, 227418, 278332, 344537, 342726], (11, ..=4096) => [-2674, 19194, 37310, 111428, 167443, 205425, 236469], (_, ..=2048) => [-1914, 10973, 70225, 173122, 240880, 305750, 293320], (_, ..=4096) => [-2651, -447, 16106, 163680, 223955, 353813, 339271], (_, _) => [-4309, -487, 21662, 26095, 83370, 157063, 543843], }
72 })
73 }
74
75 fn conf(self, output_range: usize, input_size: usize, bits_per_seed: u8, bucket_size_100: u16, preferred_slice_len: u16) -> Conf {
76 let max_shift = self.extra_shift(bits_per_seed);
77 let slice_len = match output_range.saturating_sub(max_shift as usize) {
78 n @ ..8192 => (n/2+1).next_power_of_two() as u16,
79 _ => 8192
80 }.min(if preferred_slice_len != 0 { preferred_slice_len } else {
81 match bits_per_seed {
82 ..=4 => 128,
83 ..=7 => 256,
84 8 => 512,
85 9 => 1024,
86 10 => 2048,
87 11 => 4096,
88 _ => 8192
89 }
90 });
91 Conf::new(output_range, input_size, bucket_size_100, slice_len, max_shift)
92 }
93
94 #[inline(always)] fn extra_shift(self, bits_per_seed: u8) -> u16 {
95 (1 << bits_per_seed) - 2
96 }
97
98 #[inline(always)] fn f(self, primary_code: u64, seed: u16, conf: &Conf) -> usize {
99 conf.f_shift0(primary_code) + (seed-1) as usize
100 }
101
102 #[inline]
107 fn best_seed(self, used_values: &mut Self::UsedValues, keys: &[u64], conf: &Conf, bits_per_seed: u8) -> u16 {
108 let mut without_shift_arrayvec: arrayvec::ArrayVec::<usize, 16>;
109 let mut without_shift_box: Box<[usize]>;
110 let without_shift: &mut [usize] = if keys.len() > 16 {
111 without_shift_box = shifts0(keys, conf).collect();
112 &mut without_shift_box
113 } else {
114 without_shift_arrayvec = shifts0(keys, conf).collect();
115 &mut without_shift_arrayvec
116 };
117 let last_shift = (1 << bits_per_seed) - 1;
119 for shift in (0..last_shift).step_by(64) {
120 let used = occupy_sum(0, used_values, &without_shift, shift);
121 if used != u64::MAX {
122 if self_collide(without_shift) { return 0; } let total_shift = shift + used.trailing_ones() as u16;
124 if total_shift >= last_shift { return 0; } mark_used(used_values, without_shift, total_shift);
127 return total_shift + 1;
128 }
129 }
130 0
131 }
132}
133