use std::sync::{Arc, Barrier, Mutex};
use std::thread;
use crate::buffer::{CircularBuffer, PushBuffer};
pub fn convolution(input : & PushBuffer<f64>, output : & mut PushBuffer<f64>,
window : Box<[f64]>, barrier : Arc<Barrier>, state : & bool)
{
let mut internal_buffer = PushBuffer::<f64>::new(window.len());
let mut index = 0;
internal_buffer.index = internal_buffer.len() - 1;
while ! * state
{
(0..internal_buffer.len()).for_each(|x| output[index] = internal_buffer[x] * window[x]);
if index < input.len() { index += 1; }
barrier.wait();
}
}
pub struct Saturation
{
ths : f64,
lim : f64,
gap : f64,
rad_pow : f64,
org : f64
}
impl Saturation
{
pub fn new(ths : f64, lim : f64) -> Self
{
let gap = lim - ths;
let side = ((gap * 2.0).powi(2) + gap.powi(2)).sqrt();
let ang = 180.0 - 2.0 * (gap * 2.0 / side).asin();
let rad = side / (2.0 * (ang/2.0).sin());
let rad_pow = rad.powi(2);
let org = lim - rad;
return Self { ths, lim, gap, rad_pow, org }
}
}
pub fn saturation(data : f64, upper : Saturation, lower : Saturation) -> f64
{
return if data > upper.lim + upper.gap { upper.lim }
else if data > upper.ths { upper.org + (upper.rad_pow - (upper.lim - data).powi(2)).sqrt() }
else if data < lower.lim - lower.gap { upper.lim }
else if data < lower.ths { lower.org - (lower.rad_pow - (lower.lim - data).powi(2)).sqrt() }
else { 0.0 }
}
pub fn process(input : & mut CircularBuffer<f64>, output : & mut CircularBuffer<f64>, next : & bool, state : Arc<bool>,
process : fn(input : & PushBuffer<f64>, output : & mut PushBuffer<f64>, barrier : Arc<Barrier>, state : & bool))
{
let input_buffer = Arc::new(Mutex::new(Some(PushBuffer::<f64>::new(input.len()))));
let output_buffer = Arc::new(Mutex::new(Some(PushBuffer::<f64>::new(output.len()))));
let barrier = Arc::new(Barrier::new(2));
let input_buffer_clone = input_buffer.clone();
let output_buffer_clone = output_buffer.clone();
let barrier_clone = barrier.clone();
let state_clone = state.clone();
let mut index = 0;
input_buffer.try_lock().unwrap().as_mut().unwrap().push((* input).next());
thread::spawn(move || process(input_buffer_clone.try_lock().unwrap().as_ref().unwrap(),
output_buffer_clone.try_lock().unwrap().as_mut().unwrap(),
barrier_clone, state_clone.as_ref())).join().unwrap();
while ! * state.as_ref()
{
if * next
{
(0..input.len()).for_each(|_|
{
input_buffer.try_lock().unwrap().as_mut().unwrap().push((* input).next());
barrier.wait();
if index < output.len()
{
output.push(output_buffer.lock().unwrap().take().unwrap()[index]);
index += 1;
}
else { output.push(output_buffer.lock().unwrap().take().unwrap()[output.len()]); }
});
}
}
}