// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
letmut lehmer = Vec::new_with_capacity(end as usize)?;
letmut prev_val = 0u32; for idx in skip..(skip + end) { let val = match read(get_context(prev_val)) {
Ok(val) => val,
Err(Error::OutOfBounds(_)) => { // Estimate 1.5 bits for each remaining code let bits = (((skip + end) - idx) as usize).saturating_mul(3) / 2; return Err(Error::OutOfBounds(bits));
}
Err(e) => return Err(e),
}; if val >= size - idx { return Err(Error::InvalidPermutationLehmerCode {
size,
idx,
lehmer: val,
});
}
lehmer.push(val);
prev_val = val;
}
// Initialize the full permutation vector with skipped elements intact letmut permutation = Vec::new_with_capacity((size - skip) as usize)?;
permutation.extend(0..size);
// Decode the Lehmer code into the slice starting at `skip` let permuted_slice = decode_lehmer_code(&lehmer, &permutation[skip as usize..])?;
// Replace the target slice in `permutation`
permutation[skip as usize..].copy_from_slice(&permuted_slice);
// Ensure the permutation has the correct size
assert_eq!(permutation.len(), size as usize);
Ok(Self(Cow::Owned(permutation)))
}
pubfn compose(&mutself, other: &Permutation) {
assert_eq!(self.0.len(), other.0.len()); letmut tmp: Vec<u32> = vec![0; self.0.len()]; for (i, val) in tmp.iter_mut().enumerate().take(self.0.len()) {
*val = self.0[other.0[i] as usize]
} self.0.to_mut().copy_from_slice(&tmp[..]);
}
}
// Decodes the Lehmer code in `code` and returns the permuted slice. #[instrument(level = "debug", ret, err)] fn decode_lehmer_code(code: &[u32], permutation_slice: &[u32]) -> Result<Vec<u32>> { let n = permutation_slice.len(); if n == 0 { return Err(Error::InvalidPermutationLehmerCode {
size: 0,
idx: 0,
lehmer: 0,
});
}
let padded_n = (n as u32).next_power_of_two() as usize;
// Allocate temp array inside the function letmut temp = Vec::new_with_capacity(padded_n)?;
temp.extend((0..padded_n as u32).map(|x| value_of_lowest_1_bit(x + 1)));
for (i, permuted_item) in permuted.iter_mut().enumerate() { let code_i = *code.get(i).unwrap_or(&0);
// Adjust the maximum allowed value for code_i if code_i as usize > n - i - 1 { return Err(Error::InvalidPermutationLehmerCode {
size: n as u32,
idx: i as u32,
lehmer: code_i,
});
}
letmut rank = code_i + 1;
// Extract i-th unused element via implicit order-statistics tree. letmut bit = padded_n; letmut next = 0usize; while bit != 0 { let cand = next + bit; if cand == 0 || cand > padded_n { return Err(Error::InvalidPermutationLehmerCode {
size: n as u32,
idx: i as u32,
lehmer: code_i,
});
}
bit >>= 1; if temp[cand - 1] < rank {
next = cand;
rank -= temp[cand - 1];
}
}
*permuted_item = permutation_slice[next];
next += 1; while next <= padded_n {
temp[next - 1] -= 1;
next += value_of_lowest_1_bit(next as u32) as usize;
}
}
Ok(permuted)
}
// Decodes the Lehmer code in `code` and returns the permuted vector. #[cfg(test)] fn decode_lehmer_code_naive(code: &[u32], permutation_slice: &[u32]) -> Result<Vec<u32>> { let n = code.len(); if n == 0 { return Err(Error::InvalidPermutationLehmerCode {
size: 0,
idx: 0,
lehmer: 0,
});
}
// Ensure permutation_slice has sufficient length if permutation_slice.len() < n { return Err(Error::InvalidPermutationLehmerCode {
size: n as u32,
idx: 0,
lehmer: 0,
});
}
// Create temp array with values from permutation_slice letmut temp = permutation_slice.to_vec(); letmut permuted = Vec::new_with_capacity(n)?;
// Iterate over the Lehmer code for (i, &idx) in code.iter().enumerate() { if idx as usize >= temp.len() { return Err(Error::InvalidPermutationLehmerCode {
size: n as u32,
idx: i as u32,
lehmer: idx,
});
}
// Assign temp[idx] to permuted vector
permuted.push(temp.remove(idx as usize));
}
// Append any remaining elements from temp to permuted
permuted.extend(temp);
impl<'a> Arbitrary<'a> for PermutationInput { fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> { // Generate a reasonable size to prevent tests from taking too long let size_lehmer = u.int_in_range(1..=1000)?;
letmut lehmer: Vec<u32> = Vec::with_capacity(size_lehmer as usize); for i in0..size_lehmer { let max_val = size_lehmer - i - 1; let val = if max_val > 0 {
u.int_in_range(0..=max_val)?
} else { 0
};
lehmer.push(val);
}
letmut permutation = Vec::new(); let size_permutation = u.int_in_range(size_lehmer..=1000)?;
permutation.extend(0..size_permutation);
let num_of_swaps = u.int_in_range(0..=100)?; for _ in0..num_of_swaps { // Randomly swap two positions let pos1 = u.int_in_range(0..=size_permutation - 1)?; let pos2 = u.int_in_range(0..=size_permutation - 1)?;
permutation.swap(pos1 as usize, pos2 as usize);
}
let permutation_slice: Vec<u32> = (skip..size).collect();
let permuted = decode_lehmer_code(&code, &permutation_slice).unwrap(); let permuted_naive = decode_lehmer_code_naive(&code, &permutation_slice).unwrap();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.