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