Revision control

Copy as Markdown

Other Tools

// 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.
use crate::render::low_memory_pipeline::render_group::ChannelVec;
/// Returns a vector of &mut vals[idx[i].0][idx[i].1], in order of idx[i].2.
/// Panics if any of the indices are out of bounds or
/// (idx[i].0, idx[i].1) == (idx[j].0, idx[j].1) for i != j or indices are not
/// sorted lexicographically.
pub(super) fn get_distinct_indices<'a, T>(
vals: &'a mut [impl AsMut<[T]>],
idx: &[(usize, usize, usize)],
) -> ChannelVec<&'a mut T> {
let mut answer_buffer = ChannelVec::new();
for _ in 0..idx.len() {
answer_buffer.push(None);
}
// TODO(veluca): in theory, we don't really need to first create a vector of
// `Option`s that then get `unwrap`-ed separately. Currently, this function
// uses somewhere between 0.5 and 1.5% of the total runtime; if that number
// increases, it might be worth investigating how to speed this up.
let mut targets = idx.iter();
let mut target = targets.next().unwrap();
'outer: for (aa, bufs) in vals.iter_mut().enumerate() {
for (bb, buf) in bufs.as_mut().iter_mut().enumerate() {
let (a, b, pos) = target;
if aa == *a && bb == *b {
answer_buffer[*pos] = Some(buf);
if let Some(t) = targets.next() {
target = t;
} else {
break 'outer;
}
}
}
}
answer_buffer
.iter_mut()
.map(|x| std::mem::take(x).expect("Not all elements were found"))
.collect()
}
/// Mirror-reflects a value v to fit in a [0; s) range.
pub(super) fn mirror(mut v: isize, s: usize) -> usize {
// TODO(veluca): consider speeding this up if needed.
loop {
if v < 0 {
v = -v - 1;
} else if v >= s as isize {
v = s as isize * 2 - v - 1;
} else {
return v as usize;
}
}
}