use crate::performance::{MemoryAnalyzer, ParallelAggregations};
use crate::series::Series;
use crate::types::Value;
use crate::VeloxxError;
pub trait SeriesPerformanceExt {
fn simd_add(&self, other: &Series) -> Result<Series, VeloxxError>;
fn par_sum(&self) -> Result<Value, VeloxxError>;
fn par_mean(&self) -> Result<Value, VeloxxError>;
fn par_min(&self) -> Result<Value, VeloxxError>;
fn par_max(&self) -> Result<Value, VeloxxError>;
fn memory_usage(&self) -> usize;
fn compression_suggestions(&self) -> Vec<&'static str>;
}
impl SeriesPerformanceExt for Series {
fn simd_add(&self, other: &Series) -> Result<Series, VeloxxError> {
#[cfg(all(feature = "simd", not(target_arch = "wasm32")))]
{
use crate::performance::optimized_simd::OptimizedSimdOps;
if self.len() != other.len() {
return Err(VeloxxError::InvalidOperation(
"Series must have same length for SIMD operations".to_string(),
));
}
match (self, other) {
(Series::F64(name, a, a_bitmap), Series::F64(_, b, b_bitmap)) => {
let len = a.len();
let mut result_values = vec![0.0; len];
let mut result_bitmap = vec![false; len];
for i in 0..len {
result_bitmap[i] = a_bitmap[i] & b_bitmap[i];
}
a.optimized_simd_add(b, &mut result_values);
Ok(Series::F64(
format!("{}_simd_add", name),
result_values,
result_bitmap,
))
}
(Series::I32(name, a, a_bitmap), Series::I32(_, b, b_bitmap)) => {
let len = a.len();
let mut result_values = vec![0; len];
let mut result_bitmap = vec![false; len];
for i in 0..len {
result_bitmap[i] = a_bitmap[i] & b_bitmap[i];
}
a.optimized_simd_add(b, &mut result_values);
Ok(Series::I32(
format!("{}_simd_add", name),
result_values,
result_bitmap,
))
}
_ => Err(VeloxxError::InvalidOperation(
"SIMD add only supported for F64 and I32 series with same types".to_string(),
)),
}
}
#[cfg(not(all(feature = "simd", not(target_arch = "wasm32"))))]
{
match (self, other) {
(Series::I32(name, values, bitmap), Series::I32(_, other_values, other_bitmap)) => {
let mut new_values = Vec::with_capacity(values.len());
let mut new_bitmap = Vec::with_capacity(values.len());
for i in 0..values.len().min(other_values.len()) {
if bitmap[i] && other_bitmap[i] {
new_values.push(values[i] + other_values[i]);
new_bitmap.push(true);
} else {
new_values.push(0);
new_bitmap.push(false);
}
}
Ok(Series::I32(name.clone(), new_values, new_bitmap))
}
(Series::F64(name, values, bitmap), Series::F64(_, other_values, other_bitmap)) => {
let mut new_values = Vec::with_capacity(values.len());
let mut new_bitmap = Vec::with_capacity(values.len());
for i in 0..values.len().min(other_values.len()) {
if bitmap[i] && other_bitmap[i] {
new_values.push(values[i] + other_values[i]);
new_bitmap.push(true);
} else {
new_values.push(0.0);
new_bitmap.push(false);
}
}
Ok(Series::F64(name.clone(), new_values, new_bitmap))
}
_ => Err(VeloxxError::InvalidOperation(
"Addition not supported for these series types".to_string(),
)),
}
}
}
fn par_sum(&self) -> Result<Value, VeloxxError> {
use crate::performance::parallel::ParallelAggregations;
ParallelAggregations::par_sum(self)
}
fn par_mean(&self) -> Result<Value, VeloxxError> {
ParallelAggregations::par_mean(self)
}
fn par_min(&self) -> Result<Value, VeloxxError> {
ParallelAggregations::par_min(self)
}
fn par_max(&self) -> Result<Value, VeloxxError> {
ParallelAggregations::par_max(self)
}
fn memory_usage(&self) -> usize {
use crate::performance::memory::MemoryAnalyzer;
MemoryAnalyzer::estimate_series_memory(self)
}
fn compression_suggestions(&self) -> Vec<&'static str> {
MemoryAnalyzer::suggest_compression(self)
}
}