ndarray_layout/transform/
merge.rsuse crate::ArrayLayout;
use std::{iter::zip, ops::Range};
impl<const N: usize> ArrayLayout<N> {
#[inline]
pub fn merge(&self, range: Range<usize>) -> Option<Self> {
self.merge_many(&[range])
}
pub fn merge_many(&self, args: &[Range<usize>]) -> Option<Self> {
let content = self.content();
let shape = content.shape();
let strides = content.strides();
let merged = args.iter().map(|range| range.len()).sum::<usize>();
let mut ans = Self::with_ndim(self.ndim + args.len() - merged);
let mut content = ans.content_mut();
content.set_offset(self.offset());
let mut i = 0;
let mut push = |d, s| {
content.set_shape(i, d);
content.set_stride(i, s);
i += 1;
};
let mut last_end = 0;
for range in args {
if range.is_empty() {
continue;
}
assert!(range.start >= last_end);
for j in last_end..range.start {
push(shape[j], strides[j]);
}
let mut pairs = zip(&shape[range.clone()], &strides[range.clone()]).collect::<Vec<_>>();
pairs.sort_unstable_by_key(|(_, &s)| s.unsigned_abs());
let ((&d, &s), pairs) = pairs.split_first().unwrap();
let mut d = d;
for (&d_, &s_) in pairs {
if d <= 1 || d_ <= 1 || s_ == s * d as isize {
d *= d_
} else {
return None;
}
}
push(d, s);
last_end = range.end;
}
for j in last_end..shape.len() {
push(shape[j], strides[j]);
}
Some(ans)
}
}