mech-core 0.3.4

The Mech language runtime.
Documentation
extern crate time;
use std::time::Instant;
//use mech_core::statemachines::*;
use mech_core::*;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use hashbrown::HashMap;
use std::collections::VecDeque;
use core::ops::Mul;
use core::fmt::*;
use num_traits::identities::*;
use num_traits::Zero;
use std::ops::*;

extern crate nalgebra as na;
use na::{Vector3, DVector, DMatrix, Rotation3, Matrix2x3, Matrix6, Matrix2};

#[derive(Debug, Clone)]
enum Table<T>
where T: Zero + One + Clone + PartialEq + Debug + AddAssign + MulAssign + 'static {
  Vector3(Vector3<T>),
  Matrix2x3(Matrix2x3<T>),
  Matrix6(Matrix6<T>),
  DVector(DVector<T>),
  DMatrix(DMatrix<T>),
}

impl<T> Table<T>
where T: Zero + One + Clone + PartialEq + Debug + AddAssign + MulAssign + 'static {

  fn new(rows: usize, cols: usize, default: T) -> Table<T> {
    match (rows, cols) {
      (1,3) => Table::Vector3(Vector3::from_element(default)),
      (2,3) => Table::Matrix2x3(Matrix2x3::from_element(default)),
      (6,6) => Table::Matrix6(Matrix6::from_element(default)),
      _ => Table::Vector3(Vector3::from_element(default)),
    }
  }

  fn size(&self) -> (usize,usize) {
    match self {
      Table::Vector3(_) => (1,3),
      Table::Matrix2x3(_) => (2,3),
      Table::Matrix6(_) => (6,6),
      Table::DVector(v) => (v.nrows(),1),
      Table::DMatrix(v) => (v.nrows(),v.ncols()),
    }
  }

  fn nrows(&self) -> usize {
    let (nrows, _) = self.size();
    nrows
  }

  fn ncols(&self) -> usize {
    let (_, ncols) = self.size();
    ncols
  }

  fn mat_mul(&self, rhs: &Self) -> std::result::Result<Self,MechError> {
    match (self,rhs) {
      (Table::Matrix6(mat_l),Table::Matrix6(mat_r)) => {
        let result = mat_l * mat_r;
        Ok(Table::Matrix6(result))
      }
      (Table::DMatrix(mat_l),Table::DMatrix(mat_r)) => {
        let result = mat_l * mat_r;
        Ok(Table::DMatrix(result))
      }
      _ => Err(MechError {
        tokens: vec![],
        id: 1234,
        kind: MechErrorKind::None,
        msg: String::from(""),
      }),
    }
  }

  fn add(&self, rhs: &Self) -> std::result::Result<Self,MechError> {
    match (self,rhs) {
      (Table::Matrix6(l),Table::Matrix6(r)) => {
        let result = l + r;
        Ok(Table::Matrix6(result))
      }
      (Table::DVector(l),Table::DVector(r)) => {
        let result = l + r;
        Ok(Table::DVector(result))
      }
      _ => Err(MechError {
        tokens: vec![],
        id: 1234,
        kind: MechErrorKind::None,
        msg: String::from(""),
      }),
    }
  }

  fn add_mut(&mut self, rhs: &Self) -> std::result::Result<(),MechError> {
    match (self,rhs) {
      (Table::Matrix6(l),Table::Matrix6(r)) => {
        *l += r;
        Ok(())
      }
      (Table::DVector(l),Table::DVector(r)) => {
        *l += r;
        Ok(())
      }
      _ => Err(MechError {
        tokens: vec![],
        id: 1234,
        kind: MechErrorKind::None,
        msg: String::from(""),
      }),
    }
  }

  fn add_scalar_mut(&mut self, rhs: T) -> std::result::Result<(),MechError> {
    match self {
      Table::Matrix6(l) => {
        l.add_scalar_mut(rhs);
        Ok(())
      }
      Table::DVector(l) => {
        l.add_scalar_mut(rhs);
        Ok(())
      }
      _ => Err(MechError {
        tokens: vec![],
        id: 1234,
        kind: MechErrorKind::None,
        msg: String::from(""),
      }),
    }
  }

}

fn main() {
  
  let mut a = Table::new(6,6,1 as u8);
  let b = Table::new(6,6,0 as u8);

  let n1 = 1e7 as usize;
  let q = 200;
  let mut xm = DMatrix::from_element(q, q, 1 as f32);
  let mut vm = DMatrix::from_element(q, q, 2 as f32);
  let mut outm = DMatrix::from_element(q, q, 1 as f32);

  let mut x = Table::DVector(DVector::from_element(n1, 1 as f32));
  let vx = Table::DVector(DVector::from_element(n1, 1 as f32));
  let mut y = Table::DVector(DVector::from_element(n1, 1 as f32));
  let mut vy = Table::DVector(DVector::from_element(n1, 1 as f32));
  let mut bx = Table::DVector(DVector::from_element(n1, 1 as f32));
  let mut by = Table::DVector(DVector::from_element(n1, 1 as f32));
  let mut g = Table::DVector(DVector::from_element(n1, 1 as f32));
  let mut aa = DVector::from_element(n1, 1 as f32);
  let mut bb = DVector::from_element(n1, 1 as f32);



  let n = 1e0 as usize;
  let mut total_time = VecDeque::new();  
  //loop {
  let mut max = 0.0;
  let mut min = 0.0;
  for _ in 0..100000 {
    let now = Instant::now();
    vm.mul_to(&xm,&mut outm);
    //  x.add_mut(&vx);
    //  y.add_mut(&vy);
    //  vy.add_mut(&g);
    //let ix = aa > bb;
    //let iy = y > by;
    let elapsed_time = now.elapsed();

    let cycle_duration = elapsed_time.as_nanos() as f64;
    total_time.push_back(cycle_duration);
    if total_time.len() > 10000 {
      total_time.pop_front();
    }
    if cycle_duration > max {
      max = cycle_duration;
    }
    if cycle_duration < min || min == 0.0 {
      min = cycle_duration;
    }
    let average_time: f64 = total_time.iter().sum::<f64>() / total_time.len() as f64; 
    println!("{:e} - {:0.2?}Hz", n, 1.0 / (average_time / 1_000_000_000.0));
  }
  println!("Max: {:?} Min: {:?}", 1.0 / (max / 1_000_000_000.0), 1.0 / (min / 1_000_000_000.0));



  
  let n = 1e5 as usize;
  
  let now = Instant::now();
  for _ in 0..n {
    let result = match &a.mat_mul(&b) {
      Ok(result) => result.clone(),
      _ => panic!("Oh No!"),
    };
    a = result;
  }
  let elapsed_time = now.elapsed();
  
  println!("{:?}", elapsed_time.as_nanos() as f64 / n as f64);
  //println!("{:?}", one);
  
  /*
  //println!("{:?}", vec);

  let code = r#"
  traffic_light(x,t) := { <1s>=>🟢=[6s]=>🟡=[10s]=>🔴=[10s]=>🟢 }

  t1 = traffic_light"#;

  let gn_id = hash_str("🟢");
  let yw_id = hash_str("🟡");
  let rd_id = hash_str("🔴");

  let gn_state = State::Id(gn_id);
  let yw_state = State::Id(yw_id);
  let rd_state = State::Id(rd_id);

  let mut machine: StateMachine = StateMachine::from_state(gn_state);
  machine.add_transition((gn_state, Event::TimerExpired),(yw_state,Output::SetTimer(6)));
  machine.add_transition((yw_state, Event::TimerExpired),(rd_state,Output::SetTimer(10)));
  machine.add_transition((rd_state, Event::TimerExpired),(gn_state,Output::SetTimer(10)));
  //println!("{:#?}", machine);

  
  let mut event_queue: Vec<Event> = vec![
    Event::TimerExpired
  ];

  let mut total_time = VecDeque::new();  
  loop {
    break;
    match event_queue.pop() {
      Some(event) => {
        let now = Instant::now();
        match machine.consume(event) {
          Ok(output) => {
            match output {
              Output::SetTimer(time) => {
                println!("{:?}", time);
                event_queue.push(Event::TimerExpired);
              }
              Output::Value(value) => {
                
              }
              Output::None => {
                  
              }
            }
          }
          Err(error) => {
            println!("{:?}", error);
            break;
          }
        }
        let elapsed_time = now.elapsed();
        println!("{:?}", elapsed_time);
        let cycle_duration = elapsed_time.as_nanos() as f64;
        total_time.push_back(cycle_duration);
        if total_time.len() > 1000 {
          total_time.pop_front();
        }
        let average_time: f64 = total_time.iter().sum::<f64>() / total_time.len() as f64; 
        println!("{:0.2?}Hz", 1.0 / (cycle_duration / 1_000_000_000.0));
      }
      None => {
        break;
      }
    }
  }
*/
  //println!("{:#?}", machine);
/*
    // Unsuccessful request
    let machine = Arc::new(Mutex::new(machine));
    {
        let mut lock = machine.lock().unwrap();
        let res = lock.consume(Input::Unsuccessful).unwrap();
        assert_eq!(res, Output::SetTimer);
        assert_eq!(lock.state(), &State::Open);
    }


    
    // Set up a timer
    let machine_wait = machine.clone();
    std::thread::spawn(move || {
        std::thread::sleep(Duration::new(5, 0));
        let mut lock = machine_wait.lock().unwrap();
        let res = lock.consume(Input::TimerTriggered).unwrap();
        assert_eq!(res, Output::None);
        assert_eq!(lock.state(), &State::HalfOpen);
    });

    // Try to pass a request when the circuit breaker is still open
    let machine_try = machine.clone();
    std::thread::spawn(move || {
        std::thread::sleep(Duration::new(1, 0));
        let mut lock = machine_try.lock().unwrap();
        let res = lock.consume(Input::Successful);
        assert!(matches!(res, Err(TransitionError::Impossible)));
        assert_eq!(lock.state(), &State::Open);
    });

    // Test if the circit breaker was actually closed
    std::thread::sleep(Duration::new(7, 0));
    {
        let mut lock = machine.lock().unwrap();
        let res = lock.consume(Input::Successful).unwrap();
        assert_eq!(res, Output::None);
        assert_eq!(lock.state(), &State::Closed);
    }*/
  println!("Success!");
}