use crate::dtype::RawDataType;
use crate::iterator::collapse_contiguous::collapse_to_uniform_stride;
use crate::iterator::flat_index_generator::FlatIndexGenerator;
use crate::{Constructors, NdArray, StridedMemory};
use std::ptr::copy_nonoverlapping;
impl<'a, T: RawDataType> NdArray<'a, T> {
#[allow(clippy::should_implement_trait)]
pub fn clone<'r>(&self) -> NdArray<'r, T> {
unsafe { NdArray::from_contiguous_owned_buffer(self.shape.clone(), self.clone_data()) }
}
pub(super) fn clone_data(&self) -> Vec<T> {
if self.is_contiguous() {
return unsafe { self.clone_data_contiguous() };
}
unsafe { self.clone_data_non_contiguous() }
}
unsafe fn clone_data_contiguous(&self) -> Vec<T> {
let mut data = Vec::with_capacity(self.len);
copy_nonoverlapping(self.ptr(), data.as_mut_ptr(), self.len);
data.set_len(self.len);
data
}
unsafe fn clone_data_non_contiguous(&self) -> Vec<T> {
let size = self.size();
let mut data = Vec::with_capacity(size);
let (mut shape, mut stride) = collapse_to_uniform_stride(&self.shape, &self.stride);
let &mut mut contiguous_stride = stride.last_mut().unwrap();
if contiguous_stride == 1 {
contiguous_stride = shape.pop().unwrap();
stride.pop();
}
else {
contiguous_stride = 1;
}
let src = self.ptr();
let mut dst = data.as_mut_ptr();
for i in FlatIndexGenerator::from(&shape, &stride) {
copy_nonoverlapping(src.add(i), dst, contiguous_stride);
dst = dst.add(contiguous_stride);
}
data.set_len(size);
data
}
}