use crate::*;
use std::cell::RefCell;
use std::rc::Rc;
use std::fmt::*;
use num_traits::*;
#[cfg(feature = "parallel")]
use rayon::prelude::*;
use std::thread;
lazy_static! {
pub static ref LOGIC_AND: u64 = hash_str("logic/and");
pub static ref LOGIC_OR: u64 = hash_str("logic/or");
pub static ref LOGIC_NOT: u64 = hash_str("logic/not");
pub static ref LOGIC_XOR: u64 = hash_str("logic/xor");
}
logic_infix_ss!(AndSS,&&);
logic_infix_ss!(OrSS,||);
logic_infix_ss!(XorSS,^);
logic_infix_vv!(AndVV,&&);
logic_infix_vv!(OrVV,||);
logic_infix_vv!(XorVV,^);
#[cfg(feature = "parallel")]
logic_infix_par_vv!(ParAndVV,&&);
#[cfg(feature = "parallel")]
logic_infix_par_vv!(ParOrVV,||);
#[cfg(feature = "parallel")]
logic_infix_par_vv!(ParXorVV,^);
logic_infix_vs!(AndVS,&&);
logic_infix_vs!(OrVS,||);
logic_infix_vs!(XorVS,^);
#[cfg(feature = "parallel")]
logic_infix_par_vs!(ParAndVS,&&);
#[cfg(feature = "parallel")]
logic_infix_par_vs!(ParOrVS,||);
#[cfg(feature = "parallel")]
logic_infix_par_vs!(ParXorVS,^);
logic_infix_sv!(AndSV,&&);
logic_infix_sv!(OrSV,||);
logic_infix_sv!(XorSV,^);
#[cfg(feature = "parallel")]
logic_infix_par_sv!(ParAndSV,&&);
#[cfg(feature = "parallel")]
logic_infix_par_sv!(ParOrSV,||);
#[cfg(feature = "parallel")]
logic_infix_par_sv!(ParXorSV,^);
logic_compiler!(LogicAnd,AndSS,AndVS,AndSV,AndVV);
logic_compiler!(LoigicOr,OrSS,OrVS,OrSV,OrVV);
logic_compiler!(LogicXor,XorSS,XorVS,XorSV,XorVV);
#[macro_export]
macro_rules! logic_infix_ss {
($func_name:ident, $op:tt) => (
#[derive(Debug)]
pub struct $func_name
{
pub lhs: ColumnV<bool>, pub rhs: ColumnV<bool>, pub out: ColumnV<bool>
}
impl MechFunction for $func_name
{
fn solve(&self) {
(self.out.borrow_mut())[0] = (self.lhs.borrow())[0] $op (self.rhs.borrow())[0];
}
fn to_string(&self) -> String { format!("{:#?}", self)}
}
)
}
#[macro_export]
macro_rules! logic_infix_vv {
($func_name:ident, $op:tt) => (
#[derive(Debug)]
pub struct $func_name {
pub lhs: ColumnV<bool>, pub rhs: ColumnV<bool>, pub out: ColumnV<bool>
}
impl MechFunction for $func_name {
fn solve(&self) {
self.out.borrow_mut().iter_mut().zip(self.lhs.borrow().iter()).zip(self.rhs.borrow().iter()).for_each(|((out, lhs), rhs)| *out = *lhs $op *rhs);
}
fn to_string(&self) -> String { format!("{:#?}", self)}
}
)
}
#[macro_export]
macro_rules! logic_infix_par_vv {
($func_name:ident, $op:tt) => (
#[cfg(feature = "parallel")]
#[derive(Debug)]
pub struct $func_name {
pub lhs: ColumnV<bool>, pub rhs: ColumnV<bool>, pub out: ColumnV<bool>
}
impl MechFunction for $func_name {
fn solve(&self) {
self.out.borrow_mut().par_iter_mut().zip(self.lhs.borrow().par_iter()).zip(self.rhs.borrow().par_iter()).for_each(|((out, lhs), rhs)| *out = *lhs $op *rhs);
}
fn to_string(&self) -> String { format!("{:#?}", self)}
}
)
}
#[macro_export]
macro_rules! logic_infix_vs {
($func_name:ident, $op:tt) => (
#[derive(Debug)]
pub struct $func_name {
pub lhs: ColumnV<bool>, pub rhs: ColumnV<bool>, pub out: ColumnV<bool>
}
impl MechFunction for $func_name {
fn solve(&self) {
let rhs = self.rhs.borrow()[0];
self.out.borrow_mut().iter_mut().zip(self.lhs.borrow().iter()).for_each(|(out, lhs)| *out = *lhs $op rhs);
}
fn to_string(&self) -> String { format!("{:#?}", self)}
}
)
}
#[macro_export]
macro_rules! logic_infix_par_vs {
($func_name:ident, $op:tt) => (
#[cfg(feature = "parallel")]
#[derive(Debug)]
pub struct $func_name {
pub lhs: ColumnV<bool>, pub rhs: ColumnV<bool>, pub out: ColumnV<bool>
}
impl MechFunction for $func_name {
fn solve(&self) {
let rhs = self.rhs.borrow()[0];
self.out.borrow_mut().par_iter_mut().zip(self.lhs.borrow().par_iter()).for_each(|(out, lhs)| *out = *lhs $op rhs);
}
fn to_string(&self) -> String { format!("{:#?}", self)}
}
)
}
#[macro_export]
macro_rules! logic_infix_sv {
($func_name:ident, $op:tt) => (
#[derive(Debug)]
pub struct $func_name {
pub lhs: ColumnV<bool>, pub rhs: ColumnV<bool>, pub out: ColumnV<bool>
}
impl MechFunction for $func_name {
fn solve(&self) {
let lhs = self.lhs.borrow()[0];
self.out.borrow_mut().iter_mut().zip(self.rhs.borrow().iter()).for_each(|(out, rhs)| *out = lhs $op *rhs);
}
fn to_string(&self) -> String { format!("{:#?}", self)}
}
)
}
#[macro_export]
macro_rules! logic_infix_par_sv {
($func_name:ident, $op:tt) => (
#[cfg(feature = "parallel")]
#[derive(Debug)]
pub struct $func_name {
pub lhs: ColumnV<bool>, pub rhs: ColumnV<bool>, pub out: ColumnV<bool>
}
impl MechFunction for $func_name {
fn solve(&self) {
let lhs = self.lhs.borrow()[0];
self.out.borrow_mut().par_iter_mut().zip(self.rhs.borrow().par_iter()).for_each(|(out, rhs)| *out = lhs $op *rhs);
}
fn to_string(&self) -> String { format!("{:#?}", self)}
}
)
}
#[derive(Debug)]
pub struct NotV {
pub arg: ColumnV<bool>, pub out: ColumnV<bool>
}
impl MechFunction for NotV {
fn solve(&self) {
self.out.borrow_mut().iter_mut().zip(self.arg.borrow().iter()).for_each(|(out, arg)| *out = !(*arg));
}
fn to_string(&self) -> String { format!("{:#?}", self)}
}
#[derive(Debug)]
pub struct NotD {
pub arg: ColumnV<bool>,
pub out: ColumnV<bool>,
pub out_table: OutTable,
}
impl MechFunction for NotD {
fn solve(&self) {
let arg = self.arg.borrow();
{
let mut out_table_brrw = self.out_table.borrow_mut();
out_table_brrw.resize(arg.len(),1);
}
self.out.borrow_mut()
.iter_mut()
.zip(arg.iter())
.for_each(|(out, arg)| *out = !(*arg));
}
fn to_string(&self) -> String { format!("{:#?}", self)}
}
#[derive(Debug)]
pub struct NotS
{
pub arg: ColumnV<bool>, pub out: ColumnV<bool>
}
impl MechFunction for NotS
{
fn solve(&self) {
(self.out.borrow_mut())[0] = !(self.arg.borrow())[0];
}
fn to_string(&self) -> String { format!("{:#?}", self)}
}
pub struct LogicNot {}
impl MechFunctionCompiler for LogicNot {
fn compile(&self, block: &mut Block, arguments: &Vec<Argument>, out: &Out) -> std::result::Result<(),MechError> {
let arg_dims = block.get_arg_dims(&arguments)?;
match &arg_dims[0] {
TableShape::Column(rows) => {
let mut argument_columns = block.get_arg_columns(arguments)?;
let out_column = block.get_out_column(out, *rows, ValueKind::Bool)?;
match (&argument_columns[0], &out_column) {
((_,Column::Bool(arg),_), Column::Bool(out)) => {
block.plan.push(NotV{arg: arg.clone(), out: out.clone() });
}
x => {return Err(MechError{tokens: vec![], msg: "".to_string(), id: 8213, kind: MechErrorKind::GenericError(format!("{:?}",x))});},
}
}
TableShape::Scalar => {
let mut argument_columns = block.get_arg_columns(arguments)?;
let out_column = block.get_out_column(out, 1, ValueKind::Bool)?;
match (&argument_columns[0], &out_column) {
((_,Column::Bool(arg),_), Column::Bool(out)) => {
block.plan.push(NotS{arg: arg.clone(), out: out.clone() });
}
x => {return Err(MechError{tokens: vec![], msg: "".to_string(), id: 8214, kind: MechErrorKind::GenericError(format!("{:?}",x))});},
}
}
TableShape::Dynamic(rows,1) => {
let (out_table_id,_,_) = &out;
let out_table = block.get_table(out_table_id)?;
{
let mut out_table_brrw = out_table.borrow_mut();
out_table_brrw.dynamic = true;
}
let mut argument_columns = block.get_arg_columns(arguments)?;
let out_column = block.get_out_column(out, *rows, ValueKind::Bool)?;
match (&argument_columns[0], &out_column) {
((_,Column::Bool(arg),_), Column::Bool(out)) => {
block.plan.push(NotD{arg: arg.clone(), out: out.clone(), out_table: out_table.clone() });
}
x => {return Err(MechError{tokens: vec![], msg: "".to_string(), id: 8213, kind: MechErrorKind::GenericError(format!("{:?}",x))});},
}
}
TableShape::Pending(table_id) => {return Err(MechError{tokens: vec![], msg: "".to_string(), id: 8215, kind: MechErrorKind::PendingTable(*table_id)});},
x => {return Err(MechError{tokens: vec![], msg: "".to_string(), id: 8219, kind: MechErrorKind::GenericError(format!("{:?}",x))});},
}
Ok(())
}
}
#[macro_export]
macro_rules! logic_compiler {
($func_name:ident, $op1:tt,$op2:tt,$op3:tt,$op4:tt) => (
pub struct $func_name {}
impl MechFunctionCompiler for $func_name {
fn compile(&self, block: &mut Block, arguments: &Vec<Argument>, out: &Out) -> std::result::Result<(),MechError> {
let arg_dims = block.get_arg_dims(&arguments)?;
match (&arg_dims[0],&arg_dims[1]) {
(TableShape::Scalar, TableShape::Scalar) => {
let mut argument_columns = block.get_arg_columns(arguments)?;
let out_column = block.get_out_column(out, 1, ValueKind::Bool)?;
match (&argument_columns[0], &argument_columns[1], &out_column) {
((_,Column::Bool(lhs),_), (_,Column::Bool(rhs),_), Column::Bool(out)) => {
block.plan.push($op1{lhs: lhs.clone(), rhs: rhs.clone(), out: out.clone() });
}
x => {return Err(MechError{tokens: vec![], msg: "".to_string(), id: 8216, kind: MechErrorKind::GenericError(format!("{:?}",x))});},
}
}
(TableShape::Column(lhs_rows), TableShape::Column(rhs_rows)) => {
let mut argument_columns = block.get_arg_columns(arguments)?;
let out_column = block.get_out_column(out, *lhs_rows, ValueKind::Bool)?;
match (&argument_columns[0], &argument_columns[1], &out_column) {
((_,Column::Bool(lhs),_), (_,Column::Bool(rhs),_), Column::Bool(out)) => {
block.plan.push($op4{lhs: lhs.clone(), rhs: rhs.clone(), out: out.clone() });
}
x => {return Err(MechError{tokens: vec![], msg: "".to_string(), id: 8217, kind: MechErrorKind::GenericError(format!("{:?}",x))});},
}
}
x => {return Err(MechError{tokens: vec![], msg: "".to_string(), id: 8218, kind: MechErrorKind::GenericError(format!("{:?}",x))});},
}
Ok(())
}
}
)
}