#[cfg(feature = "sse")]
#[link(name = "accumulate")]
extern "C" {
fn accumulate_sse(src: *const f32, dst: *mut u8, n: u32);
}
#[cfg(feature = "sse")]
pub fn accumulate(src: &[f32]) -> Vec<u8> {
let len = src.len();
let n = (len + 3) & !3; let mut dst: Vec<u8> = Vec::with_capacity(n);
unsafe {
accumulate_sse(src.as_ptr(), dst.as_mut_ptr(), n as u32);
dst.set_len(len); }
dst
}
#[cfg(not(feature = "sse"))]
pub fn accumulate(src: &[f32]) -> Vec<u8> {
let mut acc = 0.0;
src.iter()
.map(|c| {
acc += c;
let y = acc.abs();
let y = if y < 1.0 { y } else { 1.0 };
(255.0 * y) as u8
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
fn accumulate_simple_impl(src: &[f32]) -> Vec<u8> {
let mut acc = 0.0;
src.iter()
.map(|c| {
acc += c;
let y = acc.abs();
let y = if y < 1.0 { y } else { 1.0 };
(255.0 * y) as u8
})
.collect()
}
fn test_accumulate(src: Vec<f32>) {
assert_eq!(accumulate_simple_impl(&src), accumulate(&src));
}
#[test]
fn max_255_from_1_0() {
test_accumulate(vec![1.0]);
}
#[test]
fn max_255_from_0_5() {
test_accumulate(vec![0.5; 2]);
}
#[test]
fn max_255_from_0_25() {
test_accumulate(vec![0.25; 4]);
}
#[test]
fn max_255_from_0_125() {
test_accumulate(vec![0.125; 8]);
}
#[test]
fn max_255_from_0_0625() {
test_accumulate(vec![0.0625; 16]);
}
#[test]
fn max_255_from_0_03125() {
test_accumulate(vec![0.03125; 32]);
}
#[test]
fn max_255_from_0_015625() {
test_accumulate(vec![0.015625; 64]);
}
#[test]
fn max_255_from_0_0078125() {
test_accumulate(vec![0.0078125; 128]);
}
#[test]
fn simple_0() {
test_accumulate(vec![]);
}
#[test]
fn simple_1() {
test_accumulate(vec![0.1]);
}
#[test]
fn simple_2() {
test_accumulate(vec![0.1, 0.2]);
}
#[test]
fn simple_3() {
test_accumulate(vec![0.1, 0.2, 0.3]);
}
#[test]
fn simple_4() {
test_accumulate(vec![0.1, 0.2, 0.3, 0.4]);
}
#[test]
fn simple_5() {
test_accumulate(vec![0.1, 0.2, 0.3, 0.4, 0.5]);
}
#[test]
fn simple_6() {
test_accumulate(vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6]);
}
#[test]
fn simple_7() {
test_accumulate(vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7]);
}
}