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