pub fn sample_degree_set_with_values(k: usize, sample: &[usize]) -> Vec<usize> {
let d = sample.len();
if d > k {
panic!("sample length must be less than or equal to n");
}
let mut values: Vec<usize> = (0..k).collect();
for (step, &r) in sample.iter().enumerate() {
let remaining = k - step;
if r >= remaining {
panic!("sample[{step}] must be in 0..{remaining}, got {r}");
}
values.swap(r, remaining - 1);
}
let mut set = values[k - d..].to_vec();
set.sort();
set
}
pub fn sample_degree_set_equal_distance(k_prime: usize, k: usize, d: usize, start: usize, interval: usize) -> Vec<usize> {
if d > k {
panic!("d must be less than or equal to n");
}
if d == 0 {
return vec![];
}
if interval == 0 {
panic!("interval must be greater than 0");
}
let mut start = start;
while start >= k {
start = (start + interval) % k_prime;
}
let mut set = Vec::with_capacity(d);
set.push(start);
for _ in 1..d {
start = (start + interval) % k_prime;
while start >= k {
start = (start + interval) % k_prime;
}
set.push(start);
}
set.sort();
set
}
pub struct CyclicStrideDegreeSets {
k: usize,
a: usize,
b: usize,
p: usize,
}
impl CyclicStrideDegreeSets {
pub fn new(k: usize) -> Self {
if k == 0 {
panic!("k must be greater than 0");
}
Self { k, a: 0, b: 1, p: 0 }
}
pub fn sample_set(&mut self, d: usize) -> Vec<usize> {
if d > self.k {
panic!("d must be less than or equal to k");
}
let mut set = Vec::with_capacity(d);
for t in 0..d {
let q = (self.p + t) % self.k;
let idx =
((self.a as u128 + (q as u128 * self.b as u128)) % self.k as u128) as usize;
set.push(idx);
}
self.p += d;
while self.p >= self.k {
self.a = (self.a + 1) % self.k;
self.b = (self.b + 1) % self.k;
while gcd_usize(self.b, self.k) != 1 {
self.b = (self.b + 1) % self.k;
}
self.p -= self.k;
}
set.sort();
set
}
pub fn sample_sets(&mut self, degrees: &[usize]) -> Vec<Vec<usize>> {
degrees.iter().map(|&d| self.sample_set(d)).collect()
}
}
fn gcd_usize(mut a: usize, mut b: usize) -> usize {
while b != 0 {
let r = a % b;
a = b;
b = r;
}
a
}