use crate::DenseTensorData;
use ariadnetor_core::backend::MemoryOrder;
use std::borrow::Cow;
pub fn reorder_data<T: Clone>(tensor: &DenseTensorData<T>, to: MemoryOrder) -> DenseTensorData<T> {
let from = tensor.order();
let shape = tensor.shape();
let rank = shape.len();
let total = tensor.len();
if from == to {
return tensor.clone();
}
if total == 0 {
return DenseTensorData::from_raw_parts(Vec::new(), shape.to_vec(), to);
}
let raw = tensor.storage().data();
let mut new_data = Vec::with_capacity(total);
let mut coords = vec![0usize; rank];
let axis_order: Vec<usize> = match to {
MemoryOrder::RowMajor => (0..rank).collect(),
MemoryOrder::ColumnMajor => (0..rank).rev().collect(),
};
for _ in 0..total {
let src_idx = flat_index(&coords, shape, from);
new_data.push(raw[src_idx].clone());
for &d in axis_order.iter().rev() {
coords[d] += 1;
if coords[d] < shape[d] {
break;
}
coords[d] = 0;
}
}
DenseTensorData::from_raw_parts(new_data, shape.to_vec(), to)
}
pub fn normalize_to_data<T: Clone>(
tensor: &DenseTensorData<T>,
target: MemoryOrder,
) -> Cow<'_, DenseTensorData<T>> {
if tensor.order() == target {
Cow::Borrowed(tensor)
} else {
Cow::Owned(reorder_data(tensor, target))
}
}
pub fn flat_index(coords: &[usize], shape: &[usize], order: MemoryOrder) -> usize {
let mut idx = 0;
let mut stride = 1;
match order {
MemoryOrder::RowMajor => {
for i in (0..shape.len()).rev() {
idx += coords[i] * stride;
stride *= shape[i];
}
}
MemoryOrder::ColumnMajor => {
for i in 0..shape.len() {
idx += coords[i] * stride;
stride *= shape[i];
}
}
}
idx
}