use rand::thread_rng;
use rand_distr::{Normal, StandardNormal, Distribution};
use std::f64::consts::PI;
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign, Mul, MulAssign, Div, DivAssign, Index, IndexMut};
use more_asserts::assert_gt;
use num::{Float, Complex, complex::ComplexFloat, NumCast};
#[derive(Debug, Clone)]
pub struct TimeSeries<D> {
fs: f64,
t0: f64,
data: Vec<D>,
}
impl<D: ComplexFloat + Float> TimeSeries<D> {
pub fn white_noise(size: usize, fs: f64, mu: D, sigma: D) -> Self
where StandardNormal: Distribution<D>
{
let rng = thread_rng();
let normal = Normal::new(mu, sigma).unwrap();
let data_vec: Vec<D> = normal.sample_iter(rng).take(size).collect();
TimeSeries::from_vector(fs, 0., data_vec)
}
}
impl<D: ComplexFloat> TimeSeries<D> {
pub fn wave(size: usize, fs: f64, freq: D, ampl: D, phase: D) -> Self {
let mut phi: D;
let mut data_vec: Vec<D> = Vec::new();
for i in 0..size {
phi = freq * NumCast::from(2. * PI * i as f64 / fs).unwrap() + phase;
data_vec.push(ampl * phi.cos());
}
TimeSeries::from_vector(fs, 0., data_vec)
}
pub fn constant(size: usize, fs: f64, value: D) -> Self {
let data_vec: Vec<D> = vec![value; size];
TimeSeries::from_vector(fs, 0., data_vec)
}
pub fn from_vector(fs: f64,
t0: f64,
input_data: Vec<D>) -> Self {
TimeSeries {
fs,
t0,
data: input_data
}
}
}
impl<D: ComplexFloat> TimeSeries<D> {
pub fn modulated_signal(
size: usize,
fs: f64,
carrier: f64,
amplitude_mod: fn(f64) -> D,
frequency_mod: fn(f64) -> f64,
phase_mod: fn(f64) -> f64
) -> TimeSeries<D> {
let mut phi: f64 = 0f64;
let mut time: f64 = 0f64;
let mut data_vec: Vec<D> = Vec::new();
for _i in 0..size {
time += 1. / fs;
phi += 2. * PI * (carrier + frequency_mod(time)) / fs;
data_vec.push(amplitude_mod(time) * D::from( (phi + phase_mod(time)).cos() ).unwrap());
}
TimeSeries::from_vector(fs, 0., data_vec)
}
}
impl<D: ComplexFloat<Real = F>, F> TimeSeries<D> {
pub fn get_size(&self) -> usize {
self.data.len()
}
pub fn get_fs(&self) -> f64 {
self.fs
}
pub fn get_t0(&self) -> f64 {
self.t0
}
pub fn get_data(&self) -> Vec<D> {
self.data.clone()
}
pub fn get_subts(&self, start: usize, end: usize) -> TimeSeries<D> {
let t0: f64 = self.t0 + (start as f64 / self.fs);
let fs = self.fs;
let mut data: Vec<D> = Vec::new();
let mut i: usize = start;
while (i < end) & (i < self.get_size()) {
data.push(self.data[i]);
i += 1;
}
TimeSeries{
fs,
t0,
data,
}
}
}
impl<D: ComplexFloat<Real = F>, F> TimeSeries<D> {
pub fn inv(&mut self) -> &mut TimeSeries<D> {
for i in 0..self.data.len() {
self.data[i] = self.data[i].recip();
}
self
}
pub fn sqrt(&mut self) -> &mut TimeSeries<D> {
for i in 0..self.data.len() {
self.data[i] = self.data[i].sqrt();
}
self
}
pub fn real(&self) -> TimeSeries<F> {
let mut output: Vec<F> = Vec::new();
for i in 0..self.data.len() {
output.push(self.data[i].re());
}
TimeSeries{
fs: self.fs,
t0: self.t0,
data: output
}
}
pub fn imag(&self) -> TimeSeries<F> {
let mut output: Vec<F> = Vec::new();
for i in 0..self.data.len() {
output.push(self.data[i].im());
}
TimeSeries{
fs: self.fs,
t0: self.t0,
data: output
}
}
pub fn abs(&self) -> TimeSeries<F> {
let mut output: Vec<F> = Vec::new();
for i in 0..self.data.len() {
output.push(self.data[i].abs());
}
TimeSeries{
fs: self.fs,
t0: self.t0,
data: output
}
}
pub fn arg(&self) -> TimeSeries<F> {
let mut output: Vec<F> = Vec::new();
for i in 0..self.data.len() {
output.push(self.data[i].arg());
}
TimeSeries{
fs: self.fs,
t0: self.t0,
data: output
}
}
pub fn mean(&self) -> D {
let mut output: D = D::zero();
for value in self.data.iter() {
output = output + *value;
}
output = output / D::from(self.get_size()).unwrap();
output
}
}
impl<D: Float> TimeSeries<D> {
pub fn max(&self) -> D {
let mut output: D = D::neg_infinity();
for sample in self.data.iter() {
if *sample > output {
output = *sample;
}
}
output
}
pub fn min(&self) -> D {
let mut output: D = D::infinity();
for sample in self.data.iter() {
if *sample < output {
output = *sample;
}
}
output
}
}
pub trait ToType {
fn to_f32(&self) -> TimeSeries<f32>;
fn to_f64(&self) -> TimeSeries<f64>;
fn to_c32(&self) -> TimeSeries<Complex<f32>>;
fn to_c64(&self) -> TimeSeries<Complex<f64>>;
}
impl<D: ComplexFloat<Real = F>, F: Float> TimeSeries<D> {
pub fn to_f32(&self) -> TimeSeries<f32> {
let mut data: Vec<f32> = Vec::new();
for i in 0..self.get_size() {
let sign: f32 = self[i].re().signum().to_f32().unwrap();
match self[i].re().to_f32() {
Some(x) => data.push(x),
None => data.push(f32::MAX * sign),
}
}
TimeSeries{
fs: self.fs,
t0: self.t0,
data: data
}
}
pub fn to_f64(&self) -> TimeSeries<f64> {
let mut data: Vec<f64> = Vec::new();
for i in 0..self.get_size() {
data.push(self[i].re().to_f64().unwrap());
}
TimeSeries{
fs: self.fs,
t0: self.t0,
data: data
}
}
pub fn to_c32(&self) -> TimeSeries<Complex<f32>> {
let mut data: Vec<Complex<f32>> = Vec::new();
for i in 0..self.get_size() {
let (real, imag): (f32, f32);
let sign_real: f32 = self[i].re().signum().to_f32().unwrap();
let sign_imag: f32 = self[i].im().signum().to_f32().unwrap();
match self[i].re().to_f32() {
Some(x) => {real = x;},
None => {real = f32::MAX * sign_real;},
}
match self[i].im().to_f32() {
Some(x) => {imag = x;},
None => {imag = f32::MAX * sign_imag;},
}
data.push(Complex{re: real, im: imag});
}
TimeSeries{
fs: self.fs,
t0: self.t0,
data: data
}
}
pub fn to_c64(&self) -> TimeSeries<Complex<f64>> {
let mut data: Vec<Complex<f64>> = Vec::new();
for i in 0..self.get_size() {
data.push(Complex{
re: self[i].re().to_f64().unwrap(),
im: self[i].im().to_f64().unwrap()
});
}
TimeSeries{
fs: self.fs,
t0: self.t0,
data: data
}
}
}
impl<'a, D> Add<&TimeSeries<D>> for &'a mut TimeSeries<D>
where D: AddAssign + ComplexFloat,
{
type Output = &'a mut TimeSeries<D>;
fn add(self, other: &TimeSeries<D>) -> &'a mut TimeSeries<D> {
assert_eq!(self.data.len(), other.data.len());
for i in 0..self.data.len() {
self.data[i] += other.data[i];
}
self
}
}
impl<'a, D> Add<D> for &'a mut TimeSeries<D>
where D: AddAssign + ComplexFloat,
{
type Output = &'a mut TimeSeries<D>;
fn add(self, other: D) -> &'a mut TimeSeries<D> {
for i in 0..self.data.len() {
self.data[i] += other;
}
self
}
}
impl<'a> Add<&'a mut TimeSeries<f32>> for f32 {
type Output = &'a mut TimeSeries<f32>;
fn add(self, other: &'a mut TimeSeries<f32>) -> &'a mut TimeSeries<f32> {
other.add(self)
}
}
impl<'a> Add<&'a mut TimeSeries<f64>> for f64 {
type Output = &'a mut TimeSeries<f64>;
fn add(self, other: &'a mut TimeSeries<f64>) -> &'a mut TimeSeries<f64> {
other.add(self)
}
}
impl<'a> Add<&'a mut TimeSeries<Complex<f32>>> for Complex<f32> {
type Output = &'a mut TimeSeries<Complex<f32>>;
fn add(self, other: &'a mut TimeSeries<Complex<f32>>) -> &'a mut TimeSeries<Complex<f32>> {
other.add(self)
}
}
impl<'a> Add<&'a mut TimeSeries<Complex<f64>>> for Complex<f64> {
type Output = &'a mut TimeSeries<Complex<f64>>;
fn add(self, other: &'a mut TimeSeries<Complex<f64>>) -> &'a mut TimeSeries<Complex<f64>> {
other.add(self)
}
}
impl<'a, D> Neg for &'a mut TimeSeries<D>
where D: MulAssign + ComplexFloat,
{
type Output = &'a mut TimeSeries<D>;
fn neg(self) -> &'a mut TimeSeries<D> {
for i in 0..self.data.len() {
self.data[i] *= NumCast::from(-1).unwrap();
}
self
}
}
impl<'a, D> Sub<&TimeSeries<D>> for &'a mut TimeSeries<D>
where D: SubAssign + ComplexFloat,
{
type Output = &'a mut TimeSeries<D>;
fn sub(self, other: &TimeSeries<D>) -> &'a mut TimeSeries<D> {
assert_eq!(self.data.len(), other.data.len());
for i in 0..self.data.len() {
self.data[i] -= other.data[i];
}
self
}
}
impl<'a, D> Sub<D> for &'a mut TimeSeries<D>
where D: SubAssign + ComplexFloat,
{
type Output = &'a mut TimeSeries<D>;
fn sub(self, other: D) -> &'a mut TimeSeries<D> {
for i in 0..self.data.len() {
self.data[i] -= other;
}
self
}
}
impl<'a> Sub<&'a mut TimeSeries<f32>> for f32 {
type Output = &'a mut TimeSeries<f32>;
fn sub(self, other: &'a mut TimeSeries<f32>) -> &'a mut TimeSeries<f32> {
other.neg().add(self)
}
}
impl<'a> Sub<&'a mut TimeSeries<f64>> for f64 {
type Output = &'a mut TimeSeries<f64>;
fn sub(self, other: &'a mut TimeSeries<f64>) -> &'a mut TimeSeries<f64> {
other.neg().add(self)
}
}
impl<'a> Sub<&'a mut TimeSeries<Complex<f32>>> for Complex<f32> {
type Output = &'a mut TimeSeries<Complex<f32>>;
fn sub(self, other: &'a mut TimeSeries<Complex<f32>>) -> &'a mut TimeSeries<Complex<f32>> {
other.neg().add(self)
}
}
impl<'a> Sub<&'a mut TimeSeries<Complex<f64>>> for Complex<f64> {
type Output = &'a mut TimeSeries<Complex<f64>>;
fn sub(self, other: &'a mut TimeSeries<Complex<f64>>) -> &'a mut TimeSeries<Complex<f64>> {
other.neg().add(self)
}
}
impl<'a, D> Mul<&TimeSeries<D>> for &'a mut TimeSeries<D>
where D: MulAssign + ComplexFloat,
{
type Output = &'a mut TimeSeries<D>;
fn mul(self, other: &TimeSeries<D>) -> &'a mut TimeSeries<D> {
assert_eq!(self.data.len(), other.data.len());
for i in 0..self.data.len() {
self.data[i] *= other.data[i];
}
self
}
}
impl<'a, D> Mul<D> for &'a mut TimeSeries<D>
where D: MulAssign + ComplexFloat,
{
type Output = &'a mut TimeSeries<D>;
fn mul(self, other: D) -> &'a mut TimeSeries<D> {
for i in 0..self.data.len() {
self.data[i] *= other;
}
self
}
}
impl<'a> Mul<&'a mut TimeSeries<f32>> for f32 {
type Output = &'a mut TimeSeries<f32>;
fn mul(self, other: &'a mut TimeSeries<f32>) -> &'a mut TimeSeries<f32> {
other.mul(self)
}
}
impl<'a> Mul<&'a mut TimeSeries<f64>> for f64 {
type Output = &'a mut TimeSeries<f64>;
fn mul(self, other: &'a mut TimeSeries<f64>) -> &'a mut TimeSeries<f64> {
other.mul(self)
}
}
impl<'a> Mul<&'a mut TimeSeries<Complex<f32>>> for Complex<f32> {
type Output = &'a mut TimeSeries<Complex<f32>>;
fn mul(self, other: &'a mut TimeSeries<Complex<f32>>) -> &'a mut TimeSeries<Complex<f32>> {
other.mul(self)
}
}
impl<'a> Mul<&'a mut TimeSeries<Complex<f64>>> for Complex<f64> {
type Output = &'a mut TimeSeries<Complex<f64>>;
fn mul(self, other: &'a mut TimeSeries<Complex<f64>>) -> &'a mut TimeSeries<Complex<f64>> {
other.mul(self)
}
}
impl<'a, D> Div<&TimeSeries<D>> for &'a mut TimeSeries<D>
where D: DivAssign + ComplexFloat,
{
type Output = &'a mut TimeSeries<D>;
fn div(self, other: &TimeSeries<D>) -> &'a mut TimeSeries<D> {
assert_eq!(self.data.len(), other.data.len());
for i in 0..self.data.len() {
self.data[i] /= other.data[i];
}
self
}
}
impl<'a, D> Div<D> for &'a mut TimeSeries<D>
where D: DivAssign + ComplexFloat,
{
type Output = &'a mut TimeSeries<D>;
fn div(self, other: D) -> &'a mut TimeSeries<D> {
for i in 0..self.data.len() {
self.data[i] /= other;
}
self
}
}
impl<'a> Div<&'a mut TimeSeries<f32>> for f32 {
type Output = &'a mut TimeSeries<f32>;
fn div(self, other: &'a mut TimeSeries<f32>) -> &'a mut TimeSeries<f32> {
other.inv().mul(self)
}
}
impl<'a> Div<&'a mut TimeSeries<f64>> for f64 {
type Output = &'a mut TimeSeries<f64>;
fn div(self, other: &'a mut TimeSeries<f64>) -> &'a mut TimeSeries<f64> {
other.inv().mul(self)
}
}
impl<'a> Div<&'a mut TimeSeries<Complex<f32>>> for Complex<f32> {
type Output = &'a mut TimeSeries<Complex<f32>>;
fn div(self, other: &'a mut TimeSeries<Complex<f32>>) -> &'a mut TimeSeries<Complex<f32>> {
other.inv().mul(self)
}
}
impl<'a> Div<&'a mut TimeSeries<Complex<f64>>> for Complex<f64> {
type Output = &'a mut TimeSeries<Complex<f64>>;
fn div(self, other: &'a mut TimeSeries<Complex<f64>>) -> &'a mut TimeSeries<Complex<f64>> {
other.inv().mul(self)
}
}
impl<D: ComplexFloat> Index<usize> for TimeSeries<D> {
type Output = D;
fn index(&self, i: usize) -> &D {
assert_gt!(self.data.len(), i);
&self.data[i]
}
}
impl<D: ComplexFloat> IndexMut<usize> for TimeSeries<D> {
fn index_mut(&mut self, i: usize) -> &mut D {
assert_gt!(self.data.len(), i);
&mut self.data[i]
}
}