use super::super::{
Buffer, BufferBorrow, Domain, DspVec, ErrorReason, MetaData, NumberSpace, ResizeOps,
ToSliceMut, Vector, VoidResult,
};
use crate::multicore_support::*;
use crate::numbers::*;
use std::mem;
use std::ptr;
use crate::{array_to_complex_mut, memcpy, memzero};
pub trait ReorganizeDataOps<T>
where
T: RealNumber,
{
fn reverse(&mut self);
fn swap_halves(&mut self);
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PaddingOption {
End,
Surround,
Center,
}
pub trait InsertZerosOps<T>
where
T: RealNumber,
{
fn zero_pad(&mut self, points: usize, option: PaddingOption) -> VoidResult;
fn zero_interleave(&mut self, factor: u32) -> VoidResult;
}
pub trait InsertZerosOpsBuffered<S, T>
where
T: RealNumber,
S: ToSliceMut<T>,
{
fn zero_pad_b<B>(&mut self, buffer: &mut B, points: usize, option: PaddingOption) -> VoidResult
where
B: for<'a> Buffer<'a, S, T>;
fn zero_interleave_b<B>(&mut self, buffer: &mut B, factor: u32)
where
B: for<'a> Buffer<'a, S, T>;
}
pub trait SplitOps {
fn split_into(&self, targets: &mut [&mut Self]) -> VoidResult;
}
pub trait MergeOps {
fn merge(&mut self, sources: &[&Self]) -> VoidResult;
}
fn reverse_array<T>(data: &mut [T])
where
T: Copy,
{
let len = data.len();
let (lo, up) = data.split_at_mut((len + 1) / 2);
for (lo, up) in lo.iter_mut().zip(up.iter_mut().rev()) {
mem::swap(lo, up);
}
}
impl<S, T, N, D> ReorganizeDataOps<T> for DspVec<S, T, N, D>
where
S: ToSliceMut<T>,
T: RealNumber,
N: NumberSpace,
D: Domain,
{
fn reverse(&mut self) {
let len = self.len();
if self.is_complex() {
let data = self.data.to_slice_mut();
let data = array_to_complex_mut(&mut data[0..len]);
reverse_array(data);
} else {
let data = self.data.to_slice_mut();
reverse_array(&mut data[0..len]);
}
}
fn swap_halves(&mut self) {
self.swap_halves_priv(true);
}
}
macro_rules! zero_interleave {
($self_: ident, $buffer: ident, $step: ident, $tuple: expr) => {{
if $step <= 1 {
return;
}
let step = $step as usize;
let old_len = $self_.len();
let new_len = step * old_len;
$self_.valid_len = new_len;
let mut target = $buffer.borrow(new_len);
{
let target = target.to_slice_mut();
let source = &$self_.data.to_slice();
Chunk::from_src_to_dest(
Complexity::Small,
&$self_.multicore_settings,
&source[0..old_len],
$tuple,
&mut target[0..new_len],
$tuple * step,
(),
move |original, range, target, _arg| {
let ptr = &mut target[0] as *mut T;
unsafe {
ptr::write_bytes(ptr, 0, new_len);
}
let skip = step * $tuple;
let mut i = 0;
let mut j = range.start;
while i < target.len() {
let original_ptr = &original[j];
let target_ptr = &mut target[i];
unsafe {
ptr::copy(original_ptr, target_ptr, $tuple);
}
j += $tuple;
i += skip;
}
},
);
}
target.trade(&mut $self_.data);
}};
}
impl<S, T, N, D> InsertZerosOps<T> for DspVec<S, T, N, D>
where
S: ToSliceMut<T>,
T: RealNumber,
N: NumberSpace,
D: Domain,
{
fn zero_pad(&mut self, points: usize, option: PaddingOption) -> VoidResult {
let len_before = self.len();
let is_complex = self.is_complex();
let step = if is_complex { 2 } else { 1 };
let len = points * step;
if len <= len_before {
return Err(ErrorReason::InvalidArgumentLength);
}
r#try!(self.resize(len));
let data = self.data.to_slice_mut();
match option {
PaddingOption::End => {
memzero(data, len_before..len);
Ok(())
}
PaddingOption::Surround => {
let diff = (len - len_before) / step;
let mut right = (diff - 1) / 2;
let mut left = diff - right;
if is_complex {
right *= 2;
left *= 2;
}
memcpy(data, 0..len_before, left);
if right > 0 {
memzero(data, len - right..len);
}
memzero(data, 0..left);
Ok(())
}
PaddingOption::Center => {
let points_before = len_before / step;
let mut right = (points_before - 1) / 2;
let mut left = points_before - right;
if is_complex {
right *= 2;
left *= 2;
}
if right > 0 {
memcpy(data, left..left + right, len - right);
}
memzero(data, left..len - right);
Ok(())
}
}
}
fn zero_interleave(&mut self, factor: u32) -> VoidResult {
let len_before = self.len();
let is_complex = self.is_complex();
let factor = factor as usize;
let len = len_before * factor;
if len < len_before {
return Ok(());
}
r#try!(self.resize(len));
if is_complex {
let data = self.data.to_slice_mut();
let data = array_to_complex_mut(data);
for j in 0..len / 2 {
let i = len / 2 - 1 - j;
if i % factor == 0 {
data[i] = data[i / factor];
} else {
data[i] = Complex::<T>::new(T::zero(), T::zero());
}
}
} else {
let data = self.data.to_slice_mut();
for j in 0..len {
let i = len - 1 - j;
if i % factor == 0 {
data[i] = data[i / factor];
} else {
data[i] = T::zero();
}
}
}
Ok(())
}
}
impl<S, T, N, D> InsertZerosOpsBuffered<S, T> for DspVec<S, T, N, D>
where
S: ToSliceMut<T>,
T: RealNumber,
N: NumberSpace,
D: Domain,
{
fn zero_pad_b<B>(&mut self, buffer: &mut B, points: usize, option: PaddingOption) -> VoidResult
where
B: for<'a> Buffer<'a, S, T>,
{
let len_before = self.len();
let is_complex = self.is_complex();
let len = if is_complex { 2 * points } else { points };
if len <= len_before {
return Err(ErrorReason::InvalidArgumentLength);
}
let mut target = buffer.borrow(len);
{
let data = self.data.to_slice();
let target = target.to_slice_mut();
self.valid_len = len;
match option {
PaddingOption::End => {
target[0..len_before].copy_from_slice(&data[0..len_before]);
memzero(target, len_before..len);
}
PaddingOption::Surround => {
let diff = (len - len_before) / if is_complex { 2 } else { 1 };
let mut right = (diff) / 2;
let mut left = diff - right;
if is_complex {
right *= 2;
left *= 2;
}
target[left..left + len_before].copy_from_slice(&data[0..len_before]);
if right > 0 {
memzero(target, len - right..len);
}
memzero(target, 0..left);
}
PaddingOption::Center => {
let step = if is_complex { 2 } else { 1 };
let points_before = len_before / step;
let mut right = points_before / 2;
let mut left = points_before - right;
if is_complex {
right *= 2;
left *= 2;
}
target[len - right..len].copy_from_slice(&data[len_before - right..len_before]);
target[0..left].copy_from_slice(&data[0..left]);
memzero(target, left..len - len_before);
}
}
}
target.trade(&mut self.data);
Ok(())
}
fn zero_interleave_b<B>(&mut self, buffer: &mut B, factor: u32)
where
B: for<'a> Buffer<'a, S, T>,
{
if self.is_complex() {
zero_interleave!(self, buffer, factor, 2)
} else {
zero_interleave!(self, buffer, factor, 1)
}
}
}
impl<S, T, N, D> SplitOps for DspVec<S, T, N, D>
where
S: ToSliceMut<T>,
T: RealNumber,
N: NumberSpace,
D: Domain,
{
fn split_into(&self, targets: &mut [&mut Self]) -> VoidResult {
let num_targets = targets.len();
let data_length = self.len();
if num_targets == 0 || data_length % num_targets != 0 {
return Err(ErrorReason::InvalidArgumentLength);
}
for t in targets.iter_mut() {
r#try!(t.resize(data_length / num_targets));
}
let data = &self.data.to_slice();
if self.is_complex() {
for i in 0..(data_length / 2) {
let target = targets[i % num_targets].data.to_slice_mut();
let pos = i / num_targets;
target[2 * pos] = data[2 * i];
target[2 * pos + 1] = data[2 * i + 1];
}
} else {
for (i, d) in data.iter().enumerate() {
let target = targets[i % num_targets].data.to_slice_mut();
let pos = i / num_targets;
target[pos] = *d;
}
}
Ok(())
}
}
impl<S, T, N, D> MergeOps for DspVec<S, T, N, D>
where
S: ToSliceMut<T>,
T: RealNumber,
N: NumberSpace,
D: Domain,
{
fn merge(&mut self, sources: &[&Self]) -> VoidResult {
{
let num_sources = sources.len();
if num_sources == 0 {
return Err(ErrorReason::InvalidArgumentLength);
}
for src in sources.iter().take(num_sources).skip(1) {
if sources[0].len() != src.len() {
return Err(ErrorReason::InvalidArgumentLength);
}
}
r#try!(self.resize(sources[0].len() * num_sources));
let data_length = self.len();
let is_complex = self.is_complex();
let data = self.data.to_slice_mut();
if is_complex {
for i in 0..(data_length / 2) {
let source = sources[i % num_sources].data.to_slice();
let pos = i / num_sources;
data[2 * i] = source[2 * pos];
data[2 * i + 1] = source[2 * pos + 1];
}
} else {
for (i, d) in data.iter_mut().enumerate() {
let source = sources[i % num_sources].data.to_slice();
let pos = i / num_sources;
*d = source[pos];
}
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::super::super::*;
#[test]
fn swap_halves_real_even_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0].to_real_time_vec();
v.swap_halves();
assert_eq!(&v[..], &[3.0, 4.0, 1.0, 2.0]);
}
#[test]
fn swap_halves_real_odd_test() {
let mut v =
vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0].to_real_time_vec();
v.swap_halves();
assert_eq!(
&v[..],
&[7.0, 8.0, 9.0, 10.0, 11.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
);
}
#[test]
fn swap_halves_complex_even_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0].to_complex_time_vec();
v.swap_halves();
assert_eq!(&v[..], &[5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0]);
}
#[test]
fn swap_halves_complex_odd_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0].to_complex_time_vec();
v.swap_halves();
assert_eq!(&v[..], &[7.0, 8.0, 9.0, 10.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
}
#[test]
fn zero_pad_end_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0].to_complex_time_vec();
v.zero_pad(9, PaddingOption::End).unwrap();
let expected = [
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_pad_surround_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0].to_complex_time_vec();
v.zero_pad(10, PaddingOption::Surround).unwrap();
let expected = [
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 0.0,
0.0, 0.0, 0.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_pad_center_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0].to_complex_time_vec();
v.zero_pad(10, PaddingOption::Center).unwrap();
let expected = [
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.0,
8.0, 9.0, 10.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_pad_b_center_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0].to_complex_time_vec();
let mut buffer = SingleBuffer::new();
v.zero_pad_b(&mut buffer, 10, PaddingOption::Center)
.unwrap();
let expected = [
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.0,
8.0, 9.0, 10.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_pad_surround_odd_signal_test() {
let mut v =
vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0].to_real_time_vec();
v.zero_pad(20, PaddingOption::Surround).unwrap();
let expected = [
0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 0.0,
0.0, 0.0, 0.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_pad_b_end_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0].to_complex_time_vec();
let mut buffer = SingleBuffer::new();
v.zero_pad_b(&mut buffer, 9, PaddingOption::End).unwrap();
let expected = [
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_pad_b_surround_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0].to_complex_time_vec();
let mut buffer = SingleBuffer::new();
v.zero_pad_b(&mut buffer, 10, PaddingOption::Surround)
.unwrap();
let expected = [
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 0.0,
0.0, 0.0, 0.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_pad_b_surround_odd_signal_test() {
let mut v = vec![
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0,
]
.to_complex_time_vec();
let mut buffer = SingleBuffer::new();
v.zero_pad_b(&mut buffer, 10, PaddingOption::Surround)
.unwrap();
let expected = [
0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 0.0,
0.0, 0.0, 0.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_pad_on_slice_fail_test() {
let a: Box<[f64]> = Box::new([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]);
let mut v = a.to_complex_time_vec();
assert_eq!(
v.zero_pad(9, PaddingOption::End),
Err(ErrorReason::TypeCanNotResize)
);
}
#[test]
fn zero_pad_on_slice_shrinked_test() {
let a: Box<[f64]> = Box::new([
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 11.0, 12.0,
13.0, 14.0,
]);
let mut v = a.to_complex_time_vec();
v.resize(10).unwrap();
v.zero_pad(9, PaddingOption::End).unwrap();
let expected = [
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_pad_surround_overlap_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0].to_complex_time_vec();
v.zero_pad(8, PaddingOption::Surround).unwrap();
let expected = [
0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 0.0, 0.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_pad_center_overlap_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0].to_complex_time_vec();
v.zero_pad(8, PaddingOption::Center).unwrap();
let expected = [
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.0, 8.0, 9.0, 10.0,
];
assert_eq!(&v[..], &expected);
}
#[test]
fn zero_interleave_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0].to_real_time_vec();
v.zero_interleave(2).unwrap();
assert_eq!(&v[..], &[1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 4.0, 0.0, 5.0, 0.0]);
}
#[test]
fn zero_interleave_even_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0].to_real_time_vec();
v.zero_interleave(2).unwrap();
assert_eq!(&v[..], &[1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 4.0, 0.0]);
}
#[test]
fn zero_interleave_b_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0, 5.0].to_real_time_vec();
let mut buffer = SingleBuffer::new();
v.zero_interleave_b(&mut buffer, 2);
assert_eq!(&v[..], &[1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 4.0, 0.0, 5.0, 0.0]);
}
#[test]
fn zero_interleave_complex_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0].to_complex_time_vec();
v.zero_interleave(2).unwrap();
assert_eq!(&v[..], &[1.0, 2.0, 0.0, 0.0, 3.0, 4.0, 0.0, 0.0]);
}
#[test]
fn zero_interleave_b_complex_test() {
let mut v = vec![1.0, 2.0, 3.0, 4.0].to_complex_time_vec();
let mut buffer = SingleBuffer::new();
v.zero_interleave_b(&mut buffer, 2);
assert_eq!(&v[..], &[1.0, 2.0, 0.0, 0.0, 3.0, 4.0, 0.0, 0.0]);
}
}