use crate::types::{ErrorKind, Value};
pub fn mode_mult_fn(args: &[Value]) -> Value {
if args.is_empty() {
return Value::Error(ErrorKind::NA);
}
let mut nums: Vec<f64> = Vec::new();
for arg in args {
match arg {
Value::Number(n) => nums.push(*n),
Value::Bool(b) => nums.push(if *b { 1.0 } else { 0.0 }),
Value::Text(s) => {
let trimmed = s.trim();
match trimmed.parse::<f64>() {
Ok(v) if v.is_finite() => nums.push(v),
_ => return Value::Error(ErrorKind::Value),
}
}
Value::Empty => {}
Value::Array(arr) => {
for v in arr {
match v {
Value::Number(n) => nums.push(*n),
Value::Error(e) => return Value::Error(e.clone()),
_ => {}
}
}
}
Value::Error(e) => return Value::Error(e.clone()),
_ => {}
}
}
if nums.is_empty() {
return Value::Error(ErrorKind::NA);
}
let mut freq: std::collections::HashMap<u64, usize> = std::collections::HashMap::new();
for &n in &nums {
*freq.entry(n.to_bits()).or_insert(0) += 1;
}
let max_count = *freq.values().max().unwrap_or(&0);
if max_count < 2 {
return Value::Error(ErrorKind::NA);
}
let mut seen: std::collections::HashSet<u64> = std::collections::HashSet::new();
let mut modes: Vec<f64> = Vec::new();
for &n in &nums {
let bits = n.to_bits();
if *freq.get(&bits).unwrap_or(&0) == max_count && seen.insert(bits) {
modes.push(n);
}
}
modes.sort_by(|a, b| a.partial_cmp(b).unwrap());
match modes.len() {
0 => Value::Error(ErrorKind::NA),
1 => Value::Number(modes[0]),
_ => Value::Array(modes.into_iter().map(|n| Value::Array(vec![Value::Number(n)])).collect()),
}
}
#[cfg(test)]
mod tests;