use arrow::array::{ArrayRef, DictionaryArray, Float32Array, Float64Array, Int16Array, Int64Array};
use arrow::datatypes::Int16Type;
use std::sync::Arc;
#[derive(Debug)]
pub enum CoordValues {
Int64(Vec<i64>),
Float32(Vec<f32>),
Float64(Vec<f64>),
}
impl CoordValues {
pub fn len(&self) -> usize {
match self {
CoordValues::Int64(v) => v.len(),
CoordValues::Float32(v) => v.len(),
CoordValues::Float64(v) => v.len(),
}
}
#[allow(dead_code)]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub fn create_coord_dictionary_typed(
values: &CoordValues,
coord_idx: usize,
coord_sizes: &[usize],
total_rows: usize,
) -> ArrayRef {
let keys = build_coord_keys(values.len(), coord_idx, coord_sizes, total_rows);
let keys_array = Int16Array::from(keys);
match values {
CoordValues::Int64(vals) => {
let values_array = Int64Array::from(vals.clone());
Arc::new(DictionaryArray::<Int16Type>::new(
keys_array,
Arc::new(values_array),
))
}
CoordValues::Float32(vals) => {
let values_array = Float32Array::from(vals.clone());
Arc::new(DictionaryArray::<Int16Type>::new(
keys_array,
Arc::new(values_array),
))
}
CoordValues::Float64(vals) => {
let values_array = Float64Array::from(vals.clone());
Arc::new(DictionaryArray::<Int16Type>::new(
keys_array,
Arc::new(values_array),
))
}
}
}
pub fn build_coord_keys(
num_values: usize,
coord_idx: usize,
coord_sizes: &[usize],
total_rows: usize,
) -> Vec<i16> {
let mut keys: Vec<i16> = Vec::with_capacity(total_rows);
let inner_size: usize = coord_sizes[coord_idx + 1..].iter().product();
let inner_size = if inner_size == 0 { 1 } else { inner_size };
let outer_count: usize = coord_sizes[..coord_idx].iter().product();
let outer_count = if outer_count == 0 { 1 } else { outer_count };
for _ in 0..outer_count {
for i in 0..num_values {
for _ in 0..inner_size {
keys.push(i as i16);
}
}
}
keys
}
pub fn calculate_limited_subset(shape: &[u64], limit: usize) -> Vec<std::ops::Range<u64>> {
let limit = limit as u64;
let mut ranges = Vec::with_capacity(shape.len());
for (i, &dim_size) in shape.iter().enumerate().rev() {
if i == shape.len() - 1 {
let take = limit.min(dim_size);
ranges.push(0..take);
} else {
let inner_size: u64 = shape[i + 1..].iter().product();
let slices_needed = limit.div_ceil(inner_size);
let take = slices_needed.min(dim_size);
ranges.push(0..take);
}
}
ranges.reverse();
ranges
}
pub fn calculate_coord_limits(coord_sizes: &[usize], limit: usize) -> Vec<usize> {
let mut limits = Vec::with_capacity(coord_sizes.len());
let n = coord_sizes.len();
for i in 0..n {
let inner_size: usize = coord_sizes[i + 1..].iter().product();
let inner_size = if inner_size == 0 { 1 } else { inner_size };
let needed = limit.div_ceil(inner_size);
let take = needed.min(coord_sizes[i]);
limits.push(take);
}
limits
}