mech_core/
lib.rs

1#![feature(get_mut_unchecked)]
2#![feature(concat_idents)]
3#![allow(warnings)]
4#![feature(iter_intersperse)]
5#![feature(extract_if)]
6#![cfg_attr(feature = "no-std", no_std)]
7#![cfg_attr(feature = "no-std", alloc)]
8#![allow(dead_code)]
9#![feature(step_trait)]
10
11#[cfg(feature="no-std")] #[macro_use] extern crate alloc;
12#[cfg(not(feature = "no-std"))] extern crate core;
13#[macro_use]
14extern crate lazy_static;
15extern crate nalgebra as na;
16extern crate tabled;
17extern crate libm;
18
19#[cfg(feature = "no-std")]
20extern crate alloc;
21extern crate core as rust_core;
22extern crate hashbrown;
23#[macro_use]
24extern crate serde_derive;
25extern crate serde;
26extern crate num_traits;
27extern crate ed25519_dalek;
28extern crate rand;
29extern crate getrandom;
30
31extern crate seahash;
32extern crate indexmap;
33use std::rc::Rc;
34use std::cell::RefCell;
35use std::fmt;
36use num_traits::*;
37use std::ops::*;
38use std::mem;
39
40pub mod value;
41pub mod matrix;
42pub mod types;
43pub mod functions;
44pub mod kind;
45pub mod error;
46pub mod nodes;
47
48pub use self::value::*;
49pub use self::matrix::*;
50pub use self::types::*;
51pub use self::functions::*;
52pub use self::kind::*;
53pub use self::error::*;
54pub use self::nodes::*;
55
56pub fn hash_chars(input: &Vec<char>) -> u64 {
57  seahash::hash(input.iter().map(|s| String::from(*s)).collect::<String>().as_bytes()) & 0x00FFFFFFFFFFFFFF
58}
59
60pub fn hash_bytes(input: &Vec<u8>) -> u64 {
61  seahash::hash(input) & 0x00FFFFFFFFFFFFFF
62}
63
64pub fn hash_str(input: &str) -> u64 {
65  seahash::hash(input.to_string().as_bytes()) & 0x00FFFFFFFFFFFFFF
66}
67
68pub fn humanize(hash: &u64) -> String {
69  let bytes: [u8; 8] = hash.to_be_bytes();
70  let mut string = "".to_string();
71  let mut ix = 0;
72  for byte in bytes.iter() {
73    if ix % 2 == 0 {
74      ix += 1;
75      continue;
76    }
77    string.push_str(&WORDLIST[*byte as usize]);
78    if ix < 7 {
79      string.push_str("-");
80    }
81    ix += 1;
82  }
83  string
84}
85
86#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
87pub enum MechSourceCode {
88  String(String),
89  Tree(Program),
90  Html(String),
91}
92
93impl MechSourceCode {
94
95  pub fn to_string(&self) -> String {
96    match self {
97      MechSourceCode::String(s) => s.clone(),
98      MechSourceCode::Tree(p) => todo!("Print the tree!"),
99      MechSourceCode::Html(h) => h.clone(),
100    }
101  }
102
103}
104
105#[derive(Clone, Debug, PartialEq, Eq)]
106pub struct IndexedString {
107  pub data: Vec<char>,
108  pub index_map: Vec<Vec<usize>>,
109  pub rows: usize,
110  pub cols: usize,
111}
112
113impl IndexedString {
114  
115  fn new(input: &str) -> Self {
116      let mut data = Vec::new();
117      let mut index_map = Vec::new();
118      let mut current_row = 0;
119      let mut current_col = 0;
120      index_map.push(Vec::new());
121      for c in input.chars() {
122        data.push(c);
123        if c == '\n' {
124          index_map.push(Vec::new());
125          current_row += 1;
126          current_col = 0;
127        } else {
128          index_map[current_row].push(data.len() - 1);
129          current_col += 1;
130        }
131      }
132      let rows = index_map.len();
133      let cols = if rows > 0 { index_map[0].len() } else { 0 };
134      IndexedString {
135          data,
136          index_map,
137          rows,
138          cols,
139      }
140  }
141
142  fn to_string(&self) -> String {
143    self.data.iter().collect()
144  }
145
146  fn get(&self, row: usize, col: usize) -> Option<char> {
147    if row < self.rows {
148      let rowz = &self.index_map[row];
149      if col < rowz.len() {
150        let index = self.index_map[row][col];
151        Some(self.data[index])
152      } else {
153        None
154      }
155    } else {
156      None
157    }
158  }
159
160  fn set(&mut self, row: usize, col: usize, new_char: char) -> Result<(), String> {
161    if row < self.rows {
162      let row_indices = &mut self.index_map[row];
163      if col < row_indices.len() {
164        let index = row_indices[col];
165        self.data[index] = new_char;
166        Ok(())
167      } else {
168        Err("Column index out of bounds".to_string())
169      }
170    } else {
171      Err("Row index out of bounds".to_string())
172    }
173  }
174}
175
176pub const WORDLIST: &[&str;256] = &[
177  "nil", "ama", "ine", "ska", "pha", "gel", "art", 
178  "ona", "sas", "ist", "aus", "pen", "ust", "umn",
179  "ado", "con", "loo", "man", "eer", "lin", "ium",
180  "ack", "som", "lue", "ird", "avo", "dog", "ger",
181  "ter", "nia", "bon", "nal", "ina", "pet", "cat",
182  "ing", "lie", "ken", "fee", "ola", "old", "rad",
183  "met", "cut", "azy", "cup", "ota", "dec", "del",
184  "elt", "iet", "don", "ble", "ear", "rth", "eas", 
185  "war", "eig", "tee", "ele", "emm", "ene", "qua",
186  "tst", "fan", "fif", "fil", "fin", "fis", "fiv", 
187  "flo", "for", "foo", "fou", "fot", "fox", "fre",
188  "fri", "fru", "gee", "gia", "glu", "fol", "gre", 
189  "ham", "hap", "har", "haw", "hel", "hig", "hot", 
190  "hyd", "ida", "ill", "ind", "ini", "ink", "iwa",
191  "and", "ite", "jer", "jig", "joh", "jul", "uly", 
192  "kan", "ket", "kil", "kin", "kit", "lac", "lak", 
193  "lem", "ard", "lim", "lio", "lit", "lon", "lou",
194  "low", "mag", "nes", "mai", "gam", "arc", "mar",
195  "mao", "mas", "may", "mex", "mic", "mik", "ril",
196  "min", "mir", "mis", "mio", "mob", "moc", "ech",
197  "moe", "tan", "oon", "ain", "mup", "sic", "neb",
198  "une", "net", "nev", "nin", "een", "nit", "nor",
199  "nov", "nut", "oct", "ohi", "okl", "one", "ora",
200  "ges", "ore", "osc", "ove", "oxy", "pap", "par", 
201  "pey", "pip", "piz", "plu", "pot", "pri", "pur",
202  "que", "uqi", "qui", "red", "riv", "rob", "roi", 
203  "rug", "sad", "sal", "sat", "sep", "sev", "eve",
204  "sha", "sie", "sin", "sik", "six", "sit", "sky", 
205  "soc", "sod", "sol", "sot", "tir", "ker", "spr",
206  "sta", "ste", "mam", "mer", "swe", "tab", "tag", 
207  "see", "nis", "tex", "thi", "the", "tim", "tri",
208  "twe", "ent", "two", "unc", "ess", "uni", "ura", 
209  "veg", "ven", "ver", "vic", "vid", "vio", "vir",
210  "was", "est", "whi", "hit", "iam", "win", "his",
211  "wis", "olf", "wyo", "ray", "ank", "yel", "zeb",
212  "ulu", "fix", "gry", "hol", "jup", "lam", "pas",
213  "rom", "sne", "ten", "uta"];
214
215// ============================================================================
216// The Standard Library!
217// ============================================================================
218
219#[macro_export]
220macro_rules! impl_binop {
221  ($struct_name:ident, $arg1_type:ty, $arg2_type:ty, $out_type:ty, $op:ident) => {
222      #[derive(Debug)]
223      struct $struct_name<T> {
224      lhs: Ref<$arg1_type>,
225      rhs: Ref<$arg2_type>,
226      out: Ref<$out_type>,
227      }
228      impl<T> MechFunction for $struct_name<T>
229      where
230      T: Copy + Debug + Clone + Sync + Send + 'static + 
231      PartialEq + PartialOrd +
232      Add<Output = T> + AddAssign +
233      Sub<Output = T> + SubAssign +
234      Mul<Output = T> + MulAssign +
235      Div<Output = T> + DivAssign +
236      Zero + One,
237      Ref<$out_type>: ToValue
238      {
239      fn solve(&self) {
240          let lhs_ptr = self.lhs.as_ptr();
241          let rhs_ptr = self.rhs.as_ptr();
242          let out_ptr = self.out.as_ptr();
243          $op!(lhs_ptr,rhs_ptr,out_ptr);
244      }
245      fn out(&self) -> Value { self.out.to_value() }
246      fn to_string(&self) -> String { format!("{:#?}", self) }
247      }};}
248
249#[macro_export]
250macro_rules! impl_bool_binop {
251  ($struct_name:ident, $arg1_type:ty, $arg2_type:ty, $out_type:ty, $op:ident) => {
252    #[derive(Debug)]
253    struct $struct_name<T> {
254      lhs: Ref<$arg1_type>,
255      rhs: Ref<$arg2_type>,
256      out: Ref<$out_type>,
257    }
258    impl<T> MechFunction for $struct_name<T>
259    where
260      T: Copy + Debug + Clone + Sync + Send + 'static + 
261      PartialEq + PartialOrd,
262      Ref<$out_type>: ToValue
263    {
264      fn solve(&self) {
265        let lhs_ptr = self.lhs.as_ptr();
266        let rhs_ptr = self.rhs.as_ptr();
267        let out_ptr = self.out.as_ptr();
268        $op!(lhs_ptr,rhs_ptr,out_ptr);
269      }
270      fn out(&self) -> Value { self.out.to_value() }
271      fn to_string(&self) -> String { format!("{:#?}", self) }
272    }};}
273
274#[macro_export]  
275macro_rules! impl_bool_urop {
276  ($struct_name:ident, $arg_type:ty, $out_type:ty, $op:ident) => {
277    #[derive(Debug)]
278    struct $struct_name<T> {
279      arg: Ref<$arg_type>,
280      out: Ref<$out_type>,
281    }
282    impl<T> MechFunction for $struct_name<T>
283    where
284      T: Copy + Debug + Clone + Sync + Send + 'static + 
285      PartialEq + PartialOrd,
286      Ref<$out_type>: ToValue
287    {
288      fn solve(&self) {
289        let arg_ptr = self.arg.as_ptr();
290        let out_ptr = self.out.as_ptr();
291        $op!(arg_ptr,out_ptr);
292      }
293      fn out(&self) -> Value { self.out.to_value() }
294      fn to_string(&self) -> String { format!("{:#?}", self) }
295    }};}
296
297#[macro_export]  
298macro_rules! impl_urop {
299  ($struct_name:ident, $arg_type:ty, $out_type:ty, $op:ident) => {
300    #[derive(Debug)]
301    struct $struct_name {
302      arg: Ref<$arg_type>,
303      out: Ref<$out_type>,
304    }
305    impl MechFunction for $struct_name {
306      fn solve(&self) {
307        let arg_ptr = self.arg.as_ptr();
308        let out_ptr = self.out.as_ptr();
309        $op!(arg_ptr,out_ptr);
310      }
311      fn out(&self) -> Value { self.out.to_value() }
312      fn to_string(&self) -> String { format!("{:#?}", self) }
313    }};}  
314
315#[macro_export]
316macro_rules! impl_fxns {
317  ($lib:ident, $in:ident, $out:ident, $op:ident) => {
318    paste!{
319      // Scalar
320      $op!([<$lib SS>], $in, $in, $out, [<$lib:lower _op>]);
321      // Scalar Matrix
322      #[cfg(feature = "Matrix1")]
323      $op!([<$lib SM1>], $in, Matrix1<$in>, Matrix1<$out>,[<$lib:lower _scalar_rhs_op>]);
324      #[cfg(feature = "Matrix2")]
325      $op!([<$lib SM2>], $in, Matrix2<$in>, Matrix2<$out>,[<$lib:lower _scalar_rhs_op>]);
326      #[cfg(feature = "Matrix3")]
327      $op!([<$lib SM3>], $in, Matrix3<$in>, Matrix3<$out>,[<$lib:lower _scalar_rhs_op>]);
328      #[cfg(feature = "Matrix4")]
329      $op!([<$lib SM4>], $in, Matrix4<$in>, Matrix4<$out>,[<$lib:lower _scalar_rhs_op>]);
330      #[cfg(feature = "Matrix2x3")]
331      $op!([<$lib SM2x3>], $in, Matrix2x3<$in>, Matrix2x3<$out>,[<$lib:lower _scalar_rhs_op>]);
332      #[cfg(feature = "Matrix3x2")]
333      $op!([<$lib SM3x2>], $in, Matrix3x2<$in>, Matrix3x2<$out>,[<$lib:lower _scalar_rhs_op>]);
334      #[cfg(feature = "MatrixD")]
335      $op!([<$lib SMD>], $in, DMatrix<$in>, DMatrix<$out>,[<$lib:lower _scalar_rhs_op>]);
336      // Scalar Row
337      #[cfg(feature = "RowVector2")]
338      $op!([<$lib SR2>], $in, RowVector2<$in>, RowVector2<$out>,[<$lib:lower _scalar_rhs_op>]);
339      #[cfg(feature = "RowVector3")]
340      $op!([<$lib SR3>], $in, RowVector3<$in>, RowVector3<$out>,[<$lib:lower _scalar_rhs_op>]);
341      #[cfg(feature = "RowVector4")]
342      $op!([<$lib SR4>], $in, RowVector4<$in>, RowVector4<$out>,[<$lib:lower _scalar_rhs_op>]);
343      #[cfg(feature = "RowVectorD")]
344      $op!([<$lib SRD>], $in, RowDVector<$in>, RowDVector<$out>,[<$lib:lower _scalar_rhs_op>]);
345      // Scalar Vector
346      #[cfg(feature = "Vector2")]
347      $op!([<$lib SV2>], $in, Vector2<$in>, Vector2<$out>,[<$lib:lower _scalar_rhs_op>]);
348      #[cfg(feature = "Vector3")]
349      $op!([<$lib SV3>], $in, Vector3<$in>, Vector3<$out>,[<$lib:lower _scalar_rhs_op>]);
350      #[cfg(feature = "Vector4")]
351      $op!([<$lib SV4>], $in, Vector4<$in>, Vector4<$out>,[<$lib:lower _scalar_rhs_op>]);
352      #[cfg(feature = "VectorD")]
353      $op!([<$lib SVD>], $in, DVector<$in>, DVector<$out>,[<$lib:lower _scalar_rhs_op>]);
354      // Matrix Scalar
355      #[cfg(feature = "Matrix1")]
356      $op!([<$lib M1S>], Matrix1<$in>, $in, Matrix1<$out>,[<$lib:lower _scalar_lhs_op>]);
357      #[cfg(feature = "Matrix2")]
358      $op!([<$lib M2S>], Matrix2<$in>, $in, Matrix2<$out>,[<$lib:lower _scalar_lhs_op>]);
359      #[cfg(feature = "Matrix3")]
360      $op!([<$lib M3S>], Matrix3<$in>, $in, Matrix3<$out>,[<$lib:lower _scalar_lhs_op>]);
361      #[cfg(feature = "Matrix4")]
362      $op!([<$lib M4S>], Matrix4<$in>, $in, Matrix4<$out>,[<$lib:lower _scalar_lhs_op>]);
363      #[cfg(feature = "Matrix2x3")]
364      $op!([<$lib M2x3S>], Matrix2x3<$in>, $in, Matrix2x3<$out>,[<$lib:lower _scalar_lhs_op>]);
365      #[cfg(feature = "Matrix3x2")]
366      $op!([<$lib M3x2S>], Matrix3x2<$in>, $in, Matrix3x2<$out>,[<$lib:lower _scalar_lhs_op>]);
367      #[cfg(feature = "MatrixD")]
368      $op!([<$lib MDS>], DMatrix<$in>, $in, DMatrix<$out>,[<$lib:lower _scalar_lhs_op>]);
369      // Row Scalar
370      #[cfg(feature = "RowVector2")]
371      $op!([<$lib R2S>], RowVector2<$in>, $in, RowVector2<$out>,[<$lib:lower _scalar_lhs_op>]);
372      #[cfg(feature = "RowVector3")]
373      $op!([<$lib R3S>], RowVector3<$in>, $in, RowVector3<$out>,[<$lib:lower _scalar_lhs_op>]);
374      #[cfg(feature = "RowVector4")]
375      $op!([<$lib R4S>], RowVector4<$in>, $in, RowVector4<$out>,[<$lib:lower _scalar_lhs_op>]);
376      #[cfg(feature = "RowVectorD")]
377      $op!([<$lib RDS>], RowDVector<$in>, $in, RowDVector<$out>,[<$lib:lower _scalar_lhs_op>]);
378      // Vector Scalar
379      #[cfg(feature = "Vector2")]
380      $op!([<$lib V2S>], Vector2<$in>, $in, Vector2<$out>,[<$lib:lower _scalar_lhs_op>]);
381      #[cfg(feature = "Vector3")]
382      $op!([<$lib V3S>], Vector3<$in>, $in, Vector3<$out>,[<$lib:lower _scalar_lhs_op>]);
383      #[cfg(feature = "Vector4")]
384      $op!([<$lib V4S>], Vector4<$in>, $in, Vector4<$out>,[<$lib:lower _scalar_lhs_op>]);
385      #[cfg(feature = "VectorD")]
386      $op!([<$lib VDS>], DVector<$in>, $in, DVector<$out>,[<$lib:lower _scalar_lhs_op>]);
387      // Matrix Matrix
388      #[cfg(feature = "Matrix1")]
389      $op!([<$lib M1M1>], Matrix1<$in>, Matrix1<$in>, Matrix1<$out>, [<$lib:lower _vec_op>]);
390      #[cfg(feature = "Matrix2")]
391      $op!([<$lib M2M2>], Matrix2<$in>, Matrix2<$in>, Matrix2<$out>, [<$lib:lower _vec_op>]);
392      #[cfg(feature = "Matrix3")]
393      $op!([<$lib M3M3>], Matrix3<$in>, Matrix3<$in>, Matrix3<$out>, [<$lib:lower _vec_op>]);
394      #[cfg(feature = "Matrix4")]
395      $op!([<$lib M4M4>], Matrix4<$in>, Matrix4<$in>, Matrix4<$out>, [<$lib:lower _vec_op>]);
396      #[cfg(feature = "Matrix2x3")]
397      $op!([<$lib M2x3M2x3>], Matrix2x3<$in>, Matrix2x3<$in>, Matrix2x3<$out>, [<$lib:lower _vec_op>]);
398      #[cfg(feature = "Matrix3x2")]
399      $op!([<$lib M3x2M3x2>], Matrix3x2<$in>, Matrix3x2<$in>, Matrix3x2<$out>, [<$lib:lower _vec_op>]);
400      #[cfg(feature = "MatrixD")]
401      $op!([<$lib MDMD>], DMatrix<$in>, DMatrix<$in>, DMatrix<$out>, [<$lib:lower _vec_op>]);
402      // Matrix Vector
403      #[cfg(feature = "Matrix2")]
404      $op!([<$lib M2V2>], Matrix2<$in>, Vector2<$in>, Matrix2<$out>, [<$lib:lower _mat_vec_op>]);
405      #[cfg(feature = "Matrix3")]
406      $op!([<$lib M3V3>], Matrix3<$in>, Vector3<$in>, Matrix3<$out>, [<$lib:lower _mat_vec_op>]);
407      #[cfg(feature = "Matrix4")]
408      $op!([<$lib M4V4>], Matrix4<$in>, Vector4<$in>, Matrix4<$out>, [<$lib:lower _mat_vec_op>]);
409      #[cfg(feature = "Matrix2x3")]
410      $op!([<$lib M2x3V2>], Matrix2x3<$in>, Vector2<$in>, Matrix2x3<$out>, [<$lib:lower _mat_vec_op>]);
411      #[cfg(feature = "Matrix3x2")]
412      $op!([<$lib M3x2V3>], Matrix3x2<$in>, Vector3<$in>, Matrix3x2<$out>, [<$lib:lower _mat_vec_op>]);
413      #[cfg(feature = "MatrixD")]
414      $op!([<$lib MDVD>], DMatrix<$in>, DVector<$in>, DMatrix<$out>, [<$lib:lower _mat_vec_op>]);
415      #[cfg(feature = "MatrixD")]
416      $op!([<$lib MDV2>], DMatrix<$in>, Vector2<$in>, DMatrix<$out>, [<$lib:lower _mat_vec_op>]);
417      #[cfg(feature = "MatrixD")]
418      $op!([<$lib MDV3>], DMatrix<$in>, Vector3<$in>, DMatrix<$out>, [<$lib:lower _mat_vec_op>]);
419      #[cfg(feature = "MatrixD")]
420      $op!([<$lib MDV4>], DMatrix<$in>, Vector4<$in>, DMatrix<$out>, [<$lib:lower _mat_vec_op>]);
421      // Vector Matrix
422      #[cfg(feature = "Vector2")]
423      $op!([<$lib V2M2>], Vector2<$in>, Matrix2<$in>, Matrix2<$out>, [<$lib:lower _vec_mat_op>]);
424      #[cfg(feature = "Vector3")]
425      $op!([<$lib V3M3>], Vector3<$in>, Matrix3<$in>, Matrix3<$out>, [<$lib:lower _vec_mat_op>]);
426      #[cfg(feature = "Vector4")]
427      $op!([<$lib V4M4>], Vector4<$in>, Matrix4<$in>, Matrix4<$out>, [<$lib:lower _vec_mat_op>]);
428      #[cfg(feature = "Vector2")]
429      $op!([<$lib V2M2x3>], Vector2<$in>, Matrix2x3<$in>, Matrix2x3<$out>, [<$lib:lower _vec_mat_op>]);
430      #[cfg(feature = "Vector3")]
431      $op!([<$lib V3M3x2>], Vector3<$in>, Matrix3x2<$in>, Matrix3x2<$out>, [<$lib:lower _vec_mat_op>]);
432      #[cfg(feature = "VectorD")]
433      $op!([<$lib VDMD>], DVector<$in>, DMatrix<$in>, DMatrix<$out>, [<$lib:lower _vec_mat_op>]);
434      #[cfg(feature = "Vector2")]
435      $op!([<$lib V2MD>], Vector2<$in>, DMatrix<$in>, DMatrix<$out>, [<$lib:lower _vec_mat_op>]);
436      #[cfg(feature = "Vector3")]
437      $op!([<$lib V3MD>], Vector3<$in>, DMatrix<$in>, DMatrix<$out>, [<$lib:lower _vec_mat_op>]);
438      #[cfg(feature = "Vector4")]
439      $op!([<$lib V4MD>], Vector4<$in>, DMatrix<$in>, DMatrix<$out>, [<$lib:lower _vec_mat_op>]);
440      // Matrix Row
441      #[cfg(feature = "Matrix2")]
442      $op!([<$lib M2R2>], Matrix2<$in>, RowVector2<$in>, Matrix2<$out>, [<$lib:lower _mat_row_op>]); 
443      #[cfg(feature = "Matrix3")]
444      $op!([<$lib M3R3>], Matrix3<$in>, RowVector3<$in>, Matrix3<$out>, [<$lib:lower _mat_row_op>]);
445      #[cfg(feature = "Matrix4")]
446      $op!([<$lib M4R4>], Matrix4<$in>, RowVector4<$in>, Matrix4<$out>, [<$lib:lower _mat_row_op>]);
447      #[cfg(feature = "Matrix2x3")]
448      $op!([<$lib M2x3R3>], Matrix2x3<$in>, RowVector3<$in>, Matrix2x3<$out>, [<$lib:lower _mat_row_op>]);
449      #[cfg(feature = "Matrix3x2")]
450      $op!([<$lib M3x2R2>], Matrix3x2<$in>, RowVector2<$in>, Matrix3x2<$out>, [<$lib:lower _mat_row_op>]);
451      #[cfg(feature = "MatrixD")]
452      $op!([<$lib MDRD>], DMatrix<$in>, RowDVector<$in>, DMatrix<$out>, [<$lib:lower _mat_row_op>]);
453      #[cfg(feature = "MatrixD")]
454      $op!([<$lib MDR2>], DMatrix<$in>, RowVector2<$in>, DMatrix<$out>, [<$lib:lower _mat_row_op>]);
455      #[cfg(feature = "MatrixD")]
456      $op!([<$lib MDR3>], DMatrix<$in>, RowVector3<$in>, DMatrix<$out>, [<$lib:lower _mat_row_op>]);
457      #[cfg(feature = "MatrixD")]
458      $op!([<$lib MDR4>], DMatrix<$in>, RowVector4<$in>, DMatrix<$out>, [<$lib:lower _mat_row_op>]); 
459      // Row Matrix
460      #[cfg(feature = "RowVector2")]
461      $op!([<$lib R2M2>], RowVector2<$in>, Matrix2<$in>, Matrix2<$out>, [<$lib:lower _row_mat_op>]); 
462      #[cfg(feature = "RowVector3")]
463      $op!([<$lib R3M3>], RowVector3<$in>, Matrix3<$in>, Matrix3<$out>, [<$lib:lower _row_mat_op>]);
464      #[cfg(feature = "RowVector4")]
465      $op!([<$lib R4M4>], RowVector4<$in>, Matrix4<$in>, Matrix4<$out>, [<$lib:lower _row_mat_op>]);
466      #[cfg(feature = "RowVector3")]
467      $op!([<$lib R3M2x3>], RowVector3<$in>, Matrix2x3<$in>, Matrix2x3<$out>, [<$lib:lower _row_mat_op>]);
468      #[cfg(feature = "RowVector2")]
469      $op!([<$lib R2M3x2>], RowVector2<$in>, Matrix3x2<$in>, Matrix3x2<$out>, [<$lib:lower _row_mat_op>]);
470      #[cfg(feature = "RowVectorD")]
471      $op!([<$lib RDMD>], RowDVector<$in>, DMatrix<$in>, DMatrix<$out>, [<$lib:lower _row_mat_op>]);
472      #[cfg(feature = "RowVector2")]
473      $op!([<$lib R2MD>], RowVector2<$in>, DMatrix<$in>, DMatrix<$out>, [<$lib:lower _row_mat_op>]);
474      #[cfg(feature = "RowVector3")]
475      $op!([<$lib R3MD>], RowVector3<$in>, DMatrix<$in>, DMatrix<$out>, [<$lib:lower _row_mat_op>]);
476      #[cfg(feature = "RowVector4")]
477      $op!([<$lib R4MD>], RowVector4<$in>, DMatrix<$in>, DMatrix<$out>, [<$lib:lower _row_mat_op>]);
478      // Row Row
479      #[cfg(feature = "RowVector2")]
480      $op!([<$lib R2R2>], RowVector2<$in>, RowVector2<$in>, RowVector2<$out>, [<$lib:lower _vec_op>]);
481      #[cfg(feature = "RowVector3")]
482      $op!([<$lib R3R3>], RowVector3<$in>, RowVector3<$in>, RowVector3<$out>, [<$lib:lower _vec_op>]);
483      #[cfg(feature = "RowVector4")]
484      $op!([<$lib R4R4>], RowVector4<$in>, RowVector4<$in>, RowVector4<$out>, [<$lib:lower _vec_op>]);
485      #[cfg(feature = "RowVectorD")]
486      $op!([<$lib RDRD>], RowDVector<$in>, RowDVector<$in>, RowDVector<$out>, [<$lib:lower _vec_op>]);
487      // Vector Vector
488      #[cfg(feature = "Vector2")]
489      $op!([<$lib V2V2>], Vector2<$in>, Vector2<$in>, Vector2<$out>, [<$lib:lower _vec_op>]);
490      #[cfg(feature = "Vector3")]
491      $op!([<$lib V3V3>], Vector3<$in>, Vector3<$in>, Vector3<$out>, [<$lib:lower _vec_op>]);
492      #[cfg(feature = "Vector4")]
493      $op!([<$lib V4V4>], Vector4<$in>, Vector4<$in>, Vector4<$out>, [<$lib:lower _vec_op>]);
494      #[cfg(feature = "VectorD")]
495      $op!([<$lib VDVD>], DVector<$in>, DVector<$in>, DVector<$out>, [<$lib:lower _vec_op>]);
496    }
497  }}
498
499#[macro_export]
500macro_rules! impl_binop_match_arms {
501  ($lib:ident, $arg:expr, $($lhs_type:ident, $rhs_type:ident => $($matrix_kind:ident, $target_type:ident, $default:expr, $value_string:tt),+);+ $(;)?) => {
502    paste!{
503      match $arg {
504        $(
505          $(
506            // Scalar Scalar
507            (Value::$lhs_type(lhs), Value::$rhs_type(rhs)) => Ok(Box::new([<$lib SS>]{lhs: lhs.clone(), rhs: rhs.clone(), out: new_ref($default) })),
508            // Scalar Matrix
509            #[cfg(all(feature = $value_string, feature = "Matrix1"))]
510            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::Matrix1(rhs))) => Ok(Box::new([<$lib SM1>]{lhs, rhs, out: new_ref(Matrix1::from_element($default))})),
511            #[cfg(all(feature = $value_string, feature = "Matrix2"))]
512            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::Matrix2(rhs))) => Ok(Box::new([<$lib SM2>]{lhs, rhs, out: new_ref(Matrix2::from_element($default))})),
513            #[cfg(all(feature = $value_string, feature = "Matrix3"))]
514            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::Matrix3(rhs))) => Ok(Box::new([<$lib SM3>]{lhs, rhs, out: new_ref(Matrix3::from_element($default))})),
515            #[cfg(all(feature = $value_string, feature = "Matrix4"))]
516            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::Matrix4(rhs))) => Ok(Box::new([<$lib SM4>]{lhs, rhs, out: new_ref(Matrix4::from_element($default))})),
517            #[cfg(all(feature = $value_string, feature = "Matrix2x3"))]
518            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::Matrix2x3(rhs))) => Ok(Box::new([<$lib SM2x3>]{lhs, rhs, out: new_ref(Matrix2x3::from_element($default))})),
519            #[cfg(all(feature = $value_string, feature = "Matrix3x2"))]
520            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::Matrix3x2(rhs))) => Ok(Box::new([<$lib SM3x2>]{lhs, rhs, out: new_ref(Matrix3x2::from_element($default))})),
521            #[cfg(all(feature = $value_string, feature = "MatrixD"))]
522            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::DMatrix(rhs))) => {
523              let (rows,cols) = {rhs.borrow().shape()};
524              Ok(Box::new([<$lib SMD>]{lhs, rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))}))},   
525            // Scalar Row
526            #[cfg(all(feature = $value_string, feature = "RowVector2"))]
527            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::RowVector2(rhs))) => Ok(Box::new([<$lib SR2>]{lhs, rhs, out: new_ref(RowVector2::from_element($default))})),
528            #[cfg(all(feature = $value_string, feature = "RowVector3"))]
529            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::RowVector3(rhs))) => Ok(Box::new([<$lib SR3>]{lhs, rhs, out: new_ref(RowVector3::from_element($default))})),
530            #[cfg(all(feature = $value_string, feature = "RowVector4"))]
531            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::RowVector4(rhs))) => Ok(Box::new([<$lib SR4>]{lhs, rhs, out: new_ref(RowVector4::from_element($default))})),
532            #[cfg(all(feature = $value_string, feature = "RowVectorD"))]
533            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::RowDVector(rhs))) => Ok(Box::new([<$lib SRD>]{lhs, rhs: rhs.clone(), out: new_ref(RowDVector::from_element(rhs.borrow().len(),$default))})),
534            // Scalar Vector
535            #[cfg(all(feature = $value_string, feature = "Vector2"))]
536            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::Vector2(rhs))) => Ok(Box::new([<$lib SV2>]{lhs, rhs, out: new_ref(Vector2::from_element($default))})),
537            #[cfg(all(feature = $value_string, feature = "Vector3"))]
538            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::Vector3(rhs))) => Ok(Box::new([<$lib SV3>]{lhs, rhs, out: new_ref(Vector3::from_element($default))})),
539            #[cfg(all(feature = $value_string, feature = "Vector4"))]
540            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::Vector4(rhs))) => Ok(Box::new([<$lib SV4>]{lhs, rhs, out: new_ref(Vector4::from_element($default))})),
541            #[cfg(all(feature = $value_string, feature = "VectorD"))]
542            (Value::$lhs_type(lhs), Value::$matrix_kind(Matrix::DVector(rhs))) => Ok(Box::new([<$lib SVD>]{lhs, rhs: rhs.clone(), out: new_ref(DVector::from_element(rhs.borrow().len(),$default))})),
543            // Matrix Scalar
544            #[cfg(all(feature = $value_string, feature = "Matrix1"))]
545            (Value::$matrix_kind(Matrix::Matrix1(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib M1S>]{lhs, rhs, out: new_ref(Matrix1::from_element($default))})),
546            #[cfg(all(feature = $value_string, feature = "Matrix2"))]
547            (Value::$matrix_kind(Matrix::Matrix2(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib M2S>]{lhs, rhs, out: new_ref(Matrix2::from_element($default))})),
548            #[cfg(all(feature = $value_string, feature = "Matrix3"))]
549            (Value::$matrix_kind(Matrix::Matrix3(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib M3S>]{lhs, rhs, out: new_ref(Matrix3::from_element($default))})),
550            #[cfg(all(feature = $value_string, feature = "Matrix4"))]
551            (Value::$matrix_kind(Matrix::Matrix4(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib M4S>]{lhs, rhs, out: new_ref(Matrix4::from_element($default))})),
552            #[cfg(all(feature = $value_string, feature = "Matrix2x3"))]
553            (Value::$matrix_kind(Matrix::Matrix2x3(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib M2x3S>]{lhs, rhs, out: new_ref(Matrix2x3::from_element($default))})),
554            #[cfg(all(feature = $value_string, feature = "Matrix3x2"))]
555            (Value::$matrix_kind(Matrix::Matrix3x2(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib M3x2S>]{lhs, rhs, out: new_ref(Matrix3x2::from_element($default))})),
556            #[cfg(all(feature = $value_string, feature = "MatrixD"))]
557            (Value::$matrix_kind(Matrix::DMatrix(lhs)),Value::$lhs_type(rhs)) => {
558              let (rows,cols) = {lhs.borrow().shape()};
559              Ok(Box::new([<$lib MDS>]{lhs: lhs.clone(), rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))}))},
560            // Row Scalar
561            #[cfg(all(feature = $value_string, feature = "RowVector2"))]
562            (Value::$matrix_kind(Matrix::RowVector2(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib R2S>]{lhs, rhs, out: new_ref(RowVector2::from_element($default))})),
563            #[cfg(all(feature = $value_string, feature = "RowVector3"))]
564            (Value::$matrix_kind(Matrix::RowVector3(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib R3S>]{lhs, rhs, out: new_ref(RowVector3::from_element($default))})),
565            #[cfg(all(feature = $value_string, feature = "RowVector4"))]
566            (Value::$matrix_kind(Matrix::RowVector4(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib R4S>]{lhs, rhs, out: new_ref(RowVector4::from_element($default))})),
567            #[cfg(all(feature = $value_string, feature = "RowVectorD"))]
568            (Value::$matrix_kind(Matrix::RowDVector(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib RDS>]{lhs: lhs.clone(), rhs, out: new_ref(RowDVector::from_element(lhs.borrow().len(),$default))})),
569            // Vector Scalar
570            #[cfg(all(feature = $value_string, feature = "Vector2"))]
571            (Value::$matrix_kind(Matrix::Vector2(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib V2S>]{lhs, rhs, out: new_ref(Vector2::from_element($default))})),
572            #[cfg(all(feature = $value_string, feature = "Vector3"))]
573            (Value::$matrix_kind(Matrix::Vector3(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib V3S>]{lhs, rhs, out: new_ref(Vector3::from_element($default))})),
574            #[cfg(all(feature = $value_string, feature = "Vector4"))]
575            (Value::$matrix_kind(Matrix::Vector4(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib V4S>]{lhs, rhs, out: new_ref(Vector4::from_element($default))})),
576            #[cfg(all(feature = $value_string, feature = "VectorD"))]
577            (Value::$matrix_kind(Matrix::DVector(lhs)),Value::$lhs_type(rhs)) => Ok(Box::new([<$lib VDS>]{lhs: lhs.clone(), rhs, out: new_ref(DVector::from_element(lhs.borrow().len(),$default))})),
578            // Matrix Matrix
579            #[cfg(all(feature = $value_string, feature = "Matrix1"))]
580            (Value::$matrix_kind(Matrix::Matrix1(lhs)), Value::$matrix_kind(Matrix::Matrix1(rhs))) => Ok(Box::new([<$lib M1M1>]{lhs, rhs, out: new_ref(Matrix1::from_element($default))})),
581            #[cfg(all(feature = $value_string, feature = "Matrix2"))]
582            (Value::$matrix_kind(Matrix::Matrix2(lhs)), Value::$matrix_kind(Matrix::Matrix2(rhs))) => Ok(Box::new([<$lib M2M2>]{lhs, rhs, out: new_ref(Matrix2::from_element($default))})),
583            #[cfg(all(feature = $value_string, feature = "Matrix3"))]
584            (Value::$matrix_kind(Matrix::Matrix3(lhs)), Value::$matrix_kind(Matrix::Matrix3(rhs))) => Ok(Box::new([<$lib M3M3>]{lhs, rhs, out: new_ref(Matrix3::from_element($default))})),
585            #[cfg(all(feature = $value_string, feature = "Matrix4"))]
586            (Value::$matrix_kind(Matrix::Matrix4(lhs)), Value::$matrix_kind(Matrix::Matrix4(rhs))) => Ok(Box::new([<$lib M4M4>]{lhs, rhs, out: new_ref(Matrix4::from_element($default))})),
587            #[cfg(all(feature = $value_string, feature = "Matrix2x3"))]
588            (Value::$matrix_kind(Matrix::Matrix2x3(lhs)), Value::$matrix_kind(Matrix::Matrix2x3(rhs))) => Ok(Box::new([<$lib M2x3M2x3>]{lhs, rhs, out: new_ref(Matrix2x3::from_element($default))})),  
589            #[cfg(all(feature = $value_string, feature = "Matrix3x2"))]
590            (Value::$matrix_kind(Matrix::Matrix3x2(lhs)), Value::$matrix_kind(Matrix::Matrix3x2(rhs))) => Ok(Box::new([<$lib M3x2M3x2>]{lhs, rhs, out: new_ref(Matrix3x2::from_element($default))})),
591            #[cfg(all(feature = $value_string, feature = "MatrixD"))]
592            (Value::$matrix_kind(Matrix::DMatrix(lhs)), Value::$matrix_kind(Matrix::DMatrix(rhs))) => {
593              let (rows,cols) = {lhs.borrow().shape()};
594              Ok(Box::new([<$lib MDMD>]{lhs, rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))}))},
595            // Row Row
596            #[cfg(all(feature = $value_string, feature = "RowVector2"))]
597            (Value::$matrix_kind(Matrix::RowVector2(lhs)), Value::$matrix_kind(Matrix::RowVector2(rhs))) => Ok(Box::new([<$lib R2R2>]{lhs: lhs.clone(), rhs: rhs.clone(), out: new_ref(RowVector2::from_element($default)) })),
598            #[cfg(all(feature = $value_string, feature = "RowVector3"))]
599            (Value::$matrix_kind(Matrix::RowVector3(lhs)), Value::$matrix_kind(Matrix::RowVector3(rhs))) => Ok(Box::new([<$lib R3R3>]{lhs: lhs.clone(), rhs: rhs.clone(), out: new_ref(RowVector3::from_element($default)) })),
600            #[cfg(all(feature = $value_string, feature = "RowVector4"))]
601            (Value::$matrix_kind(Matrix::RowVector4(lhs)), Value::$matrix_kind(Matrix::RowVector4(rhs))) => Ok(Box::new([<$lib R4R4>]{lhs: lhs.clone(), rhs: rhs.clone(), out: new_ref(RowVector4::from_element($default)) })),
602            #[cfg(all(feature = $value_string, feature = "RowVectorD"))]
603            (Value::$matrix_kind(Matrix::RowDVector(lhs)), Value::$matrix_kind(Matrix::RowDVector(rhs))) => Ok(Box::new([<$lib RDRD>]{lhs: lhs.clone(), rhs, out: new_ref(RowDVector::from_element(lhs.borrow().len(),$default))})),
604            // Vector Vector
605            #[cfg(all(feature = $value_string, feature = "Vector2"))]
606            (Value::$matrix_kind(Matrix::Vector2(lhs)), Value::$matrix_kind(Matrix::Vector2(rhs))) => Ok(Box::new([<$lib V2V2>]{lhs: lhs.clone(), rhs: rhs.clone(), out: new_ref(Vector2::from_element($default)) })),
607            #[cfg(all(feature = $value_string, feature = "Vector3"))]
608            (Value::$matrix_kind(Matrix::Vector3(lhs)), Value::$matrix_kind(Matrix::Vector3(rhs))) => Ok(Box::new([<$lib V3V3>]{lhs: lhs.clone(), rhs: rhs.clone(), out: new_ref(Vector3::from_element($default)) })),
609            #[cfg(all(feature = $value_string, feature = "Vector4"))]
610            (Value::$matrix_kind(Matrix::Vector4(lhs)), Value::$matrix_kind(Matrix::Vector4(rhs))) => Ok(Box::new([<$lib V4V4>]{lhs: lhs.clone(), rhs: rhs.clone(), out: new_ref(Vector4::from_element($default)) })),
611            #[cfg(all(feature = $value_string, feature = "VectorD"))]
612            (Value::$matrix_kind(Matrix::DVector(lhs)), Value::$matrix_kind(Matrix::DVector(rhs))) => Ok(Box::new([<$lib VDVD>]{lhs: lhs.clone(), rhs, out: new_ref(DVector::from_element(lhs.borrow().len(),$default))})),
613            // Matrix Vector     
614            #[cfg(all(feature = $value_string, feature = "Matrix2"))]
615            (Value::$matrix_kind(Matrix::Matrix2(lhs)),Value::$matrix_kind(Matrix::Vector2(rhs))) => Ok(Box::new([<$lib M2V2>]{lhs, rhs, out: new_ref(Matrix2::from_element($default))})),         
616            #[cfg(all(feature = $value_string, feature = "Matrix3"))]
617            (Value::$matrix_kind(Matrix::Matrix3(lhs)),Value::$matrix_kind(Matrix::Vector3(rhs))) => Ok(Box::new([<$lib M3V3>]{lhs, rhs, out: new_ref(Matrix3::from_element($default))})),         
618            #[cfg(all(feature = $value_string, feature = "Matrix2x3"))]
619            (Value::$matrix_kind(Matrix::Matrix2x3(lhs)),Value::$matrix_kind(Matrix::Vector2(rhs))) => Ok(Box::new([<$lib M2x3V2>]{lhs, rhs, out: new_ref(Matrix2x3::from_element($default))})),         
620            #[cfg(all(feature = $value_string, feature = "Matrix3x2"))]
621            (Value::$matrix_kind(Matrix::Matrix3x2(lhs)),Value::$matrix_kind(Matrix::Vector3(rhs))) => Ok(Box::new([<$lib M3x2V3>]{lhs, rhs, out: new_ref(Matrix3x2::from_element($default))})),         
622            #[cfg(all(feature = $value_string, feature = "Matrix4"))]
623            (Value::$matrix_kind(Matrix::Matrix4(lhs)),Value::$matrix_kind(Matrix::Vector4(rhs))) => Ok(Box::new([<$lib M4V4>]{lhs, rhs, out: new_ref(Matrix4::from_element($default))})),         
624            #[cfg(all(feature = $value_string, feature = "MatrixD"))]
625            // Matrix Row     
626            #[cfg(all(feature = $value_string, feature = "Matrix2"))]
627            (Value::$matrix_kind(Matrix::Matrix2(lhs)),Value::$matrix_kind(Matrix::RowVector2(rhs))) => Ok(Box::new([<$lib M2R2>]{lhs, rhs, out: new_ref(Matrix2::from_element($default))})),         
628            #[cfg(all(feature = $value_string, feature = "Matrix3"))]
629            (Value::$matrix_kind(Matrix::Matrix3(lhs)),Value::$matrix_kind(Matrix::RowVector3(rhs))) => Ok(Box::new([<$lib M3R3>]{lhs, rhs, out: new_ref(Matrix3::from_element($default))})),         
630            #[cfg(all(feature = $value_string, feature = "Matrix2x3"))]
631            (Value::$matrix_kind(Matrix::Matrix2x3(lhs)),Value::$matrix_kind(Matrix::RowVector3(rhs))) => Ok(Box::new([<$lib M2x3R3>]{lhs, rhs, out: new_ref(Matrix2x3::from_element($default))})),         
632            #[cfg(all(feature = $value_string, feature = "Matrix3x2"))]
633            (Value::$matrix_kind(Matrix::Matrix3x2(lhs)),Value::$matrix_kind(Matrix::RowVector2(rhs))) => Ok(Box::new([<$lib M3x2R2>]{lhs, rhs, out: new_ref(Matrix3x2::from_element($default))})),         
634            #[cfg(all(feature = $value_string, feature = "Matrix4"))]
635            (Value::$matrix_kind(Matrix::Matrix4(lhs)),Value::$matrix_kind(Matrix::RowVector4(rhs))) => Ok(Box::new([<$lib M4R4>]{lhs, rhs, out: new_ref(Matrix4::from_element($default))})),         
636            #[cfg(all(feature = $value_string, feature = "MatrixD"))]
637            (Value::$matrix_kind(Matrix::DMatrix(lhs)),Value::$matrix_kind(rhs)) => {
638              let (rows,cols) = {lhs.borrow().shape()};
639              let rhs_shape = rhs.shape();
640              match (rows,cols,rhs_shape[0],rhs_shape[1]) {
641                // matching rows
642                (n,_,m,1) if n == m => (),
643                // matching cols
644                (_,n,1,m) if n == m => (),
645                // mismatching dimensions
646                _ => {return Err(MechError{file: file!().to_string(),  tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::DimensionMismatch(vec![]) });},
647              }
648              match rhs {
649                Matrix::Vector2(rhs) => Ok(Box::new([<$lib MDV2>]{lhs: lhs.clone(), rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
650                Matrix::Vector3(rhs) => Ok(Box::new([<$lib MDV3>]{lhs: lhs.clone(), rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
651                Matrix::Vector4(rhs) => Ok(Box::new([<$lib MDV4>]{lhs: lhs.clone(), rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
652                Matrix::DVector(rhs) => Ok(Box::new([<$lib MDVD>]{lhs: lhs.clone(), rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
653                Matrix::RowVector2(rhs) => Ok(Box::new([<$lib MDR2>]{lhs: lhs.clone(), rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
654                Matrix::RowVector3(rhs) => Ok(Box::new([<$lib MDR3>]{lhs: lhs.clone(), rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
655                Matrix::RowVector4(rhs) => Ok(Box::new([<$lib MDR4>]{lhs: lhs.clone(), rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
656                Matrix::RowDVector(rhs) => Ok(Box::new([<$lib MDRD>]{lhs: lhs.clone(), rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
657                _ => {return Err(MechError{file: file!().to_string(),  tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::DimensionMismatch(vec![]) });},
658              }
659            },
660            // Vector Matrix
661            #[cfg(all(feature = $value_string, feature = "Matrix2"))]
662            (Value::$matrix_kind(Matrix::Vector2(lhs)), Value::$matrix_kind(Matrix::Matrix2(rhs))) => Ok(Box::new([<$lib V2M2>]{lhs, rhs, out: new_ref(Matrix2::from_element($default))})),         
663            #[cfg(all(feature = $value_string, feature = "Matrix3"))]
664            (Value::$matrix_kind(Matrix::Vector3(lhs)), Value::$matrix_kind(Matrix::Matrix3(rhs))) => Ok(Box::new([<$lib V3M3>]{lhs, rhs, out: new_ref(Matrix3::from_element($default))})),         
665            #[cfg(all(feature = $value_string, feature = "Matrix2x3"))]
666            (Value::$matrix_kind(Matrix::Vector2(lhs)), Value::$matrix_kind(Matrix::Matrix2x3(rhs))) => Ok(Box::new([<$lib V2M2x3>]{lhs, rhs, out: new_ref(Matrix2x3::from_element($default))})),         
667            #[cfg(all(feature = $value_string, feature = "Matrix3x2"))]
668            (Value::$matrix_kind(Matrix::Vector3(lhs)), Value::$matrix_kind(Matrix::Matrix3x2(rhs))) => Ok(Box::new([<$lib V3M3x2>]{lhs, rhs, out: new_ref(Matrix3x2::from_element($default))})),                     
669            #[cfg(all(feature = $value_string, feature = "Matrix4"))]
670            (Value::$matrix_kind(Matrix::Vector4(lhs)), Value::$matrix_kind(Matrix::Matrix4(rhs))) => Ok(Box::new([<$lib V4M4>]{lhs, rhs, out: new_ref(Matrix4::from_element($default))})),                     
671            // Row Matrix     
672            #[cfg(all(feature = $value_string, feature = "RowVector2"))]
673            (Value::$matrix_kind(Matrix::RowVector2(lhs)), Value::$matrix_kind(Matrix::Matrix2(rhs))) => Ok(Box::new([<$lib R2M2>]{lhs, rhs, out: new_ref(Matrix2::from_element($default))})),         
674            #[cfg(all(feature = $value_string, feature = "RowVector3"))]
675            (Value::$matrix_kind(Matrix::RowVector3(lhs)), Value::$matrix_kind(Matrix::Matrix3(rhs))) => Ok(Box::new([<$lib R3M3>]{lhs, rhs, out: new_ref(Matrix3::from_element($default))})),         
676            #[cfg(all(feature = $value_string, feature = "RowVector3"))]
677            (Value::$matrix_kind(Matrix::RowVector3(lhs)), Value::$matrix_kind(Matrix::Matrix2x3(rhs))) => Ok(Box::new([<$lib R3M2x3>]{lhs, rhs, out: new_ref(Matrix2x3::from_element($default))})),         
678            #[cfg(all(feature = $value_string, feature = "RowVector2"))]
679            (Value::$matrix_kind(Matrix::RowVector2(lhs)), Value::$matrix_kind(Matrix::Matrix3x2(rhs))) => Ok(Box::new([<$lib R2M3x2>]{lhs, rhs, out: new_ref(Matrix3x2::from_element($default))})),         
680            #[cfg(all(feature = $value_string, feature = "RowVector4"))]
681            (Value::$matrix_kind(Matrix::RowVector4(lhs)), Value::$matrix_kind(Matrix::Matrix4(rhs))) => Ok(Box::new([<$lib R4M4>]{lhs, rhs, out: new_ref(Matrix4::from_element($default))})),         
682            #[cfg(all(feature = $value_string, feature = "MatrixD"))]
683            (Value::$matrix_kind(lhs),Value::$matrix_kind(Matrix::DMatrix(rhs))) => {
684              let (rows,cols) = {rhs.borrow().shape()};
685              let lhs_shape = lhs.shape();
686              match (lhs_shape[0],lhs_shape[1],rows,cols) {
687                // matching rows
688                (m,1,n,_) if n == m => (),
689                // matching cols
690                (1,m,_,n) if n == m => (),
691                // mismatching dimensions
692                _ => {return Err(MechError{file: file!().to_string(),  tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::DimensionMismatch(vec![]) });},
693              }
694              match lhs {
695                Matrix::Vector2(lhs) => Ok(Box::new([<$lib V2MD>]{lhs, rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
696                Matrix::Vector3(lhs) => Ok(Box::new([<$lib V3MD>]{lhs, rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
697                Matrix::Vector4(lhs) => Ok(Box::new([<$lib V4MD>]{lhs, rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
698                Matrix::DVector(lhs) => Ok(Box::new([<$lib VDMD>]{lhs, rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
699                Matrix::RowVector2(lhs) => Ok(Box::new([<$lib R2MD>]{lhs, rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
700                Matrix::RowVector3(lhs) => Ok(Box::new([<$lib R3MD>]{lhs, rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
701                Matrix::RowVector4(lhs) => Ok(Box::new([<$lib R4MD>]{lhs, rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
702                Matrix::RowDVector(lhs) => Ok(Box::new([<$lib RDMD>]{lhs, rhs, out: new_ref(DMatrix::from_element(rows,cols,$default))})),
703                _ => {return Err(MechError{file: file!().to_string(),  tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::DimensionMismatch(vec![]) });},
704              }
705            }
706          )+
707        )+
708        x => Err(MechError{file: file!().to_string(),  tokens: vec![], msg: format!("{:?}",x), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
709      }
710    }
711  }
712}
713
714#[macro_export]
715macro_rules! impl_urnop_match_arms {
716  ($lib:ident, $arg:expr, $($lhs_type:ident => $($matrix_kind:ident, $target_type:ident, $default:expr, $value_string:tt),+);+ $(;)?) => {
717    paste!{
718      match $arg {
719        $(
720          $(
721            (Value::$lhs_type(arg)) => Ok(Box::new([<$lib S>]{arg: arg.clone(), out: new_ref($default) })),
722            #[cfg(all(feature = $value_string, feature = "Matrix1"))]
723            (Value::$matrix_kind(Matrix::Matrix1(arg))) => Ok(Box::new([<$lib M1>]{arg, out: new_ref(Matrix1::from_element($default))})),
724            #[cfg(all(feature = $value_string, feature = "Matrix2"))]
725            (Value::$matrix_kind(Matrix::Matrix2(arg))) => Ok(Box::new([<$lib M2>]{arg, out: new_ref(Matrix2::from_element($default))})),
726            #[cfg(all(feature = $value_string, feature = "Matrix3"))]
727            (Value::$matrix_kind(Matrix::Matrix3(arg))) => Ok(Box::new([<$lib M3>]{arg, out: new_ref(Matrix3::from_element($default))})),
728            #[cfg(all(feature = $value_string, feature = "Matrix4"))]
729            (Value::$matrix_kind(Matrix::Matrix4(arg))) => Ok(Box::new([<$lib M4>]{arg, out: new_ref(Matrix4::from_element($default))})),
730            #[cfg(all(feature = $value_string, feature = "Matrix2x3"))]
731            (Value::$matrix_kind(Matrix::Matrix2x3(arg))) => Ok(Box::new([<$lib M2x3>]{arg, out: new_ref(Matrix2x3::from_element($default))})),         
732            #[cfg(all(feature = $value_string, feature = "Matrix3x2"))]
733            (Value::$matrix_kind(Matrix::Matrix3x2(arg))) => Ok(Box::new([<$lib M3x2>]{arg, out: new_ref(Matrix3x2::from_element($default))})),         
734            #[cfg(all(feature = $value_string, feature = "RowVector2"))]
735            (Value::$matrix_kind(Matrix::RowVector2(arg))) => Ok(Box::new([<$lib R2>]{arg: arg.clone(), out: new_ref(RowVector2::from_element($default)) })),
736            #[cfg(all(feature = $value_string, feature = "RowVector3"))]
737            (Value::$matrix_kind(Matrix::RowVector3(arg))) => Ok(Box::new([<$lib R3>]{arg: arg.clone(), out: new_ref(RowVector3::from_element($default)) })),
738            #[cfg(all(feature = $value_string, feature = "RowVector4"))]
739            (Value::$matrix_kind(Matrix::RowVector4(arg))) => Ok(Box::new([<$lib R4>]{arg: arg.clone(), out: new_ref(RowVector4::from_element($default)) })),
740            #[cfg(all(feature = $value_string, feature = "RowVectorD"))]
741            (Value::$matrix_kind(Matrix::RowDVector(arg))) => Ok(Box::new([<$lib RD>]{arg: arg.clone(), out: new_ref(RowDVector::from_element(arg.borrow().len(),$default))})),
742            #[cfg(all(feature = $value_string, feature = "Vector2"))]
743            (Value::$matrix_kind(Matrix::Vector2(arg))) => Ok(Box::new([<$lib V2>]{arg: arg.clone(), out: new_ref(Vector2::from_element($default)) })),
744            #[cfg(all(feature = $value_string, feature = "Vector3"))]
745            (Value::$matrix_kind(Matrix::Vector3(arg))) => Ok(Box::new([<$lib V3>]{arg: arg.clone(), out: new_ref(Vector3::from_element($default)) })),
746            #[cfg(all(feature = $value_string, feature = "Vector4"))]
747            (Value::$matrix_kind(Matrix::Vector4(arg))) => Ok(Box::new([<$lib V4>]{arg: arg.clone(), out: new_ref(Vector4::from_element($default)) })),
748            #[cfg(all(feature = $value_string, feature = "VectorD"))]
749            (Value::$matrix_kind(Matrix::DVector(arg))) => Ok(Box::new([<$lib VD>]{arg: arg.clone(), out: new_ref(DVector::from_element(arg.borrow().len(),$default))})),
750            #[cfg(all(feature = $value_string, feature = "MatrixD"))]
751            (Value::$matrix_kind(Matrix::DMatrix(arg))) => {
752              let (rows,cols) = {arg.borrow().shape()};
753              Ok(Box::new([<$lib MD>]{arg, out: new_ref(DMatrix::from_element(rows,cols,$default))}))},
754          )+
755        )+
756        x => Err(MechError{file: file!().to_string(),  tokens: vec![], msg: format!("{:?}",x), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
757      }
758    }
759  }
760}
761
762#[macro_export]
763macro_rules! impl_mech_binop_fxn {
764  ($fxn_name:ident, $gen_fxn:ident) => {
765    pub struct $fxn_name {}
766    impl NativeFunctionCompiler for $fxn_name {
767      fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
768        if arguments.len() != 2 {
769          return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
770        }
771        let lhs_value = arguments[0].clone();
772        let rhs_value = arguments[1].clone();
773        match $gen_fxn(lhs_value.clone(), rhs_value.clone()) {
774          Ok(fxn) => Ok(fxn),
775          Err(_) => {
776            match (lhs_value,rhs_value) {
777              (Value::MutableReference(lhs),Value::MutableReference(rhs)) => {$gen_fxn(lhs.borrow().clone(), rhs.borrow().clone())}
778              (lhs_value,Value::MutableReference(rhs)) => { $gen_fxn(lhs_value.clone(), rhs.borrow().clone())}
779              (Value::MutableReference(lhs),rhs_value) => { $gen_fxn(lhs.borrow().clone(), rhs_value.clone()) }
780              x => Err(MechError{file: file!().to_string(),  tokens: vec![], msg: format!("{:?}",x), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
781            }
782          }
783        }
784      }
785    }
786  }
787}
788
789#[macro_export]
790macro_rules! impl_mech_urnop_fxn {
791  ($fxn_name:ident, $gen_fxn:ident) => {
792    pub struct $fxn_name {}
793    impl NativeFunctionCompiler for $fxn_name {
794      fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
795        if arguments.len() != 1 {
796          return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
797        }
798        let input = arguments[0].clone();
799        match $gen_fxn(input.clone()) {
800          Ok(fxn) => Ok(fxn),
801          Err(_) => {
802            match (input) {
803              (Value::MutableReference(input)) => {$gen_fxn(input.borrow().clone())}
804              x => Err(MechError{file: file!().to_string(),  tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
805            }
806          }
807        }
808      }
809    }
810  }
811}