diff --git a/src/cell_dir.rs b/src/cell_dir.rs index 7c71edd..a52669d 100644 --- a/src/cell_dir.rs +++ b/src/cell_dir.rs @@ -73,6 +73,73 @@ impl CellDir { } } + pub fn path_from_to(mut a: (usize, usize), b: (usize, usize)) + -> Vec + { + let mut path = vec![]; + + let mut defensive_max : i32 = 1024; + + while (a.0 != b.0 || a.1 != b.1) && defensive_max > 0 { + //d// println!("ITER START: A={:?} B={:?}", a, b); + defensive_max -= 1; + + let mut min_distance = 99999.0; + let mut min_dir = CellDir::C; + let mut min_new_a = a; + + for e in 0..6 { + let dir = Self::from(e); + + if let Some(new_pos) = dir.offs_pos(a) { + let dist = + (b.0 as f32 - new_pos.0 as f32).powf(2.0) + + (b.1 as f32 - new_pos.1 as f32).powf(2.0); + + //d// println!("DIST={:5.3} FOR {:?} (B={:?})", dist, new_pos, b); + + if dist < min_distance { + min_distance = dist; + min_dir = dir; + min_new_a = new_pos; + } + } else { + //d// println!("NOPOS {:?} {:?}", dir, a); + } + } + + if min_distance < 99999.0 { + //d// println!("A={:?} => {:?} DIR={:?} B={:?}", a, min_new_a, min_dir, b); + a = min_new_a; + path.push(min_dir); + } else { + //d// println!("ITER BREAK"); + break; + } + + //d// println!("ITER END: A={:?} B={:?} MAX={}", a, b, defensive_max); + } + + //d// println!("PATH: {:?}", path); + + path + } + + pub fn offs_pos(&self, pos: (usize, usize)) -> Option<(usize, usize)> { + let offs = self.as_offs(pos.0); + + let new_pos = ( + pos.0 as i32 + offs.0, + pos.1 as i32 + offs.1 + ); + + if new_pos.0 >= 0 && new_pos.1 >= 0 { + Some((new_pos.0 as usize, new_pos.1 as usize)) + } else { + None + } + } + pub fn as_offs(&self, x: usize) -> (i32, i32) { let even = x % 2 == 0; match self { diff --git a/src/matrix.rs b/src/matrix.rs index 1fc3420..6f59125 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -36,7 +36,7 @@ use std::collections::{HashMap, HashSet}; /// /// matrix.sync().unwrap(); ///``` -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] pub struct Cell { node_id: NodeId, x: u8, @@ -178,6 +178,20 @@ impl Cell { (self.x as usize, self.y as usize) } + pub fn offs_dir(&mut self, dir: CellDir) -> bool { + if let Some(new_pos) = + dir.offs_pos((self.x as usize, self.y as usize)) + { + self.x = new_pos.0 as u8; + self.y = new_pos.1 as u8; + true + } + else + { + false + } + } + pub fn has_dir_set(&self, dir: CellDir) -> bool { match dir { CellDir::TR => self.out1.is_some(), @@ -258,6 +272,8 @@ pub enum MatrixError { output1: (NodeId, u8), output2: (NodeId, u8), }, + NonEmptyCell { cell: Cell }, + PosOutOfRange } /// An intermediate data structure to store a single edge in the [Matrix]. @@ -443,6 +459,58 @@ impl Matrix { } } + /// Like [Matrix::change_matrix] but the function passed to this + /// needs to return a `Result<(), MatrixError>`. + pub fn change_matrix_err(&mut self, mut f: F) + -> Result<(), MatrixError> + where F: FnMut(&mut Self) -> Result<(), MatrixError> + { + self.save_matrix(); + + if let Err(e) = f(self) { + self.restore_matrix(); + return Err(e); + } + + if let Err(e) = self.check() { + self.restore_matrix(); + Err(e) + } else { + Ok(()) + } + } + + /// Tries to place all `cells` at once, if they are placed in empty + /// cells only! Returns an error of the destination cell is not empty + /// or out of range, or if the placement of the cluster results in any + /// other inconsistencies. + /// + /// This action must be wrapped with [Matrix::change_matrix_err]! + /// + /// Restores the matrix to the previous state if placing fails. + pub fn place_multiple(&mut self, cells: &[Cell]) -> Result<(), MatrixError> { + for cell in cells { + let x = cell.pos().0; + let y = cell.pos().1; + + if let Some(existing) = self.get(x, y) { + if !existing.is_empty() { + return Err(MatrixError::NonEmptyCell { cell: *existing }); + } + + self.place(x, y, *cell); + } else { + return Err(MatrixError::PosOutOfRange); + } + } + + if let Err(e) = self.check() { + Err(e) + } else { + Ok(()) + } + } + /// Inserts a cell into the hexagonal grid of the matrix. /// You have to make sure that the resulting DSP graph topology /// does not have cycles, otherwise an upload to the DSP thread via diff --git a/src/nodes/node_exec.rs b/src/nodes/node_exec.rs index f665de7..d64d28d 100644 --- a/src/nodes/node_exec.rs +++ b/src/nodes/node_exec.rs @@ -17,6 +17,12 @@ use crate::log; use ringbuf::{Producer, Consumer}; use std::sync::Arc; +use core::arch::x86_64::{ + _MM_FLUSH_ZERO_ON, + _MM_SET_FLUSH_ZERO_MODE, +// _MM_GET_FLUSH_ZERO_MODE +}; + /// Holds the complete allocation of nodes and /// the program. New Nodes or the program is /// not newly allocated in the audio backend, but it is @@ -256,6 +262,8 @@ impl NodeExecutor { GraphMessage::NewProg { prog, copy_old_out } => { let mut prev_prog = std::mem::replace(&mut self.prog, prog); + unsafe { _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); } + self.monitor_signal_cur_inp_indices = [UNUSED_MONITOR_IDX; MON_SIG_CNT];