mech_interpreter/stdlib/
horzcat.rs

1#[macro_use]
2use crate::stdlib::*;
3
4// Horizontal Concatenate -----------------------------------------------------
5
6macro_rules! horzcat_one_arg {
7  ($fxn:ident, $e0:ident, $out:ident, $opt:ident) => {
8    #[derive(Debug)]
9    struct $fxn<T> {
10      e0: Ref<$e0<T>>,
11      out: Ref<$out<T>>,
12    }
13    impl<T> MechFunction for $fxn<T>
14    where
15      T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
16      Ref<$out<T>>: ToValue
17    {
18      fn solve(&self) { 
19        unsafe {
20          let e0_ptr = (*(self.e0.as_ptr())).clone();
21          let mut out_ptr = (&mut *(self.out.as_ptr()));
22          $opt!(out_ptr,e0_ptr);
23        }
24      }
25      fn out(&self) -> Value { self.out.to_value() }
26      fn to_string(&self) -> String { format!("{:#?}", self) }
27    }
28  };}
29
30macro_rules! horzcat_two_args {
31  ($fxn:ident, $e1:ident, $e2:ident, $out:ident, $opt:ident) => {
32    #[derive(Debug)]
33    struct $fxn<T> {
34      e0: Ref<$e1<T>>,
35      e1: Ref<$e2<T>>,
36      out: Ref<$out<T>>,
37    }
38    impl<T> MechFunction for $fxn<T>
39    where
40      T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
41      Ref<$out<T>>: ToValue
42    {
43      fn solve(&self) { 
44        unsafe {
45          let e0_ptr = (*(self.e0.as_ptr())).clone();
46          let e1_ptr = (*(self.e1.as_ptr())).clone();
47          let mut out_ptr = (&mut *(self.out.as_ptr()));
48          $opt!(out_ptr,e0_ptr,e1_ptr);
49        }
50      }
51      fn out(&self) -> Value { self.out.to_value() }
52      fn to_string(&self) -> String { format!("{:#?}", self) }
53    }
54  };}
55
56macro_rules! horzcat_three_args {
57  ($fxn:ident, $e0:ident, $e1:ident, $e2:ident, $out:ident, $opt:ident) => {
58    #[derive(Debug)]
59    struct $fxn<T> {
60      e0: Ref<$e0<T>>,
61      e1: Ref<$e1<T>>,
62      e2: Ref<$e2<T>>,
63      out: Ref<$out<T>>,
64    }
65    impl<T> MechFunction for $fxn<T>
66    where
67      T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
68      Ref<$out<T>>: ToValue
69    {
70      fn solve(&self) { 
71        unsafe {
72          let e0_ptr = (*(self.e0.as_ptr())).clone();
73          let e1_ptr = (*(self.e1.as_ptr())).clone();
74          let e2_ptr = (*(self.e2.as_ptr())).clone();
75          let mut out_ptr = (&mut *(self.out.as_ptr()));
76          $opt!(out_ptr,e0_ptr,e1_ptr,e2_ptr);
77        }
78      }
79      fn out(&self) -> Value { self.out.to_value() }
80      fn to_string(&self) -> String { format!("{:#?}", self) }
81    }
82  };} 
83  
84macro_rules! horzcat_four_args {
85  ($fxn:ident, $e0:ident, $e1:ident, $e2:ident, $e3:ident, $out:ident, $opt:ident) => {
86    #[derive(Debug)]
87    struct $fxn<T> {
88      e0: Ref<$e0<T>>,
89      e1: Ref<$e1<T>>,
90      e2: Ref<$e2<T>>,
91      e3: Ref<$e3<T>>,
92      out: Ref<$out<T>>,
93    }
94    impl<T> MechFunction for $fxn<T>
95    where
96      T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
97      Ref<$out<T>>: ToValue
98    {
99      fn solve(&self) { 
100        unsafe {
101          let e0_ptr = (*(self.e0.as_ptr())).clone();
102          let e1_ptr = (*(self.e1.as_ptr())).clone();
103          let e2_ptr = (*(self.e2.as_ptr())).clone();
104          let e3_ptr = (*(self.e3.as_ptr())).clone();
105          let mut out_ptr = (&mut *(self.out.as_ptr()));
106          $opt!(out_ptr,e0_ptr,e1_ptr,e2_ptr,e3_ptr);
107        }
108      }
109      fn out(&self) -> Value { self.out.to_value() }
110      fn to_string(&self) -> String { format!("{:#?}", self) }
111    }
112  };}   
113
114struct HorizontalConcatenateTwoArgs<T> {
115  e0: Box<dyn CopyMat<T>>,
116  e1: Box<dyn CopyMat<T>>,
117  out: Ref<DMatrix<T>>,
118}
119impl<T> MechFunction for HorizontalConcatenateTwoArgs<T>
120where
121  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
122  Ref<DMatrix<T>>: ToValue
123{
124  fn solve(&self) {
125    let offset = self.e0.copy_into(&self.out,0);
126    self.e1.copy_into(&self.out,offset);
127  }
128  fn out(&self) -> Value { self.out.to_value() }
129  fn to_string(&self) -> String { format!("HorizontalConcatenateTwoArgs\n{:#?}", self.out) }
130}
131    
132struct HorizontalConcatenateThreeArgs<T> {
133  e0: Box<dyn CopyMat<T>>,
134  e1: Box<dyn CopyMat<T>>,
135  e2: Box<dyn CopyMat<T>>,
136  out: Ref<DMatrix<T>>,
137}
138impl<T> MechFunction for HorizontalConcatenateThreeArgs<T>
139where
140  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
141  Ref<DMatrix<T>>: ToValue
142{
143  fn solve(&self) {
144    let mut offset = self.e0.copy_into(&self.out,0);
145    offset += self.e1.copy_into(&self.out,offset);
146    self.e2.copy_into(&self.out,offset);
147  }
148  fn out(&self) -> Value { self.out.to_value() }
149  fn to_string(&self) -> String { format!("HorizontalConcatenateThreeArgs\n{:#?}", self.out) }
150}
151
152struct HorizontalConcatenateFourArgs<T> {
153  e0: Box<dyn CopyMat<T>>,
154  e1: Box<dyn CopyMat<T>>,
155  e2: Box<dyn CopyMat<T>>,
156  e3: Box<dyn CopyMat<T>>,
157  out: Ref<DMatrix<T>>,
158}
159impl<T> MechFunction for HorizontalConcatenateFourArgs<T>
160where
161  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
162  Ref<DMatrix<T>>: ToValue
163{
164  fn solve(&self) {
165    let mut offset = self.e0.copy_into(&self.out,0);
166    offset += self.e1.copy_into(&self.out,offset);
167    offset += self.e2.copy_into(&self.out,offset);
168    self.e3.copy_into(&self.out,offset);
169
170  }
171  fn out(&self) -> Value { self.out.to_value() }
172  fn to_string(&self) -> String { format!("HorizontalConcatenateFourArgs\n{:#?}", self.out) }
173}
174
175struct HorizontalConcatenateNArgs<T> {
176  e0: Vec<Box<dyn CopyMat<T>>>,
177  out: Ref<DMatrix<T>>,
178}
179impl<T> MechFunction for HorizontalConcatenateNArgs<T>
180where
181  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
182  Ref<DMatrix<T>>: ToValue
183{
184  fn solve(&self) {
185    let mut offset = 0;
186    for e in &self.e0 {
187      offset += e.copy_into(&self.out,offset);
188    }
189  }
190  fn out(&self) -> Value { self.out.to_value() }
191  fn to_string(&self) -> String { format!("HorizontalConcatenateNArgs\n{:#?}", self.out) }
192}
193
194macro_rules! horizontal_concatenate {
195  ($name:ident, $vec_size:expr) => {
196    paste!{
197      #[derive(Debug)]
198      struct $name<T> {
199        out: Ref<[<RowVector $vec_size>]<T>>,
200      }
201
202      impl<T> MechFunction for $name<T> 
203      where
204        T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
205        Ref<[<RowVector $vec_size>]<T>>: ToValue
206      {
207        fn solve(&self) {}
208        fn out(&self) -> Value { self.out.to_value() }
209        fn to_string(&self) -> String { format!("{:#?}", self) }
210      }
211    }
212  };}  
213
214#[derive(Debug)]
215struct HorizontalConcatenateRD<T> {
216  out: Ref<RowDVector<T>>,
217}
218
219impl<T> MechFunction for HorizontalConcatenateRD<T> 
220where
221  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
222  Ref<RowDVector<T>>: ToValue
223{
224  fn solve(&self) {}
225  fn out(&self) -> Value { self.out.to_value() }
226  fn to_string(&self) -> String { format!("{:#?}", self) }
227}
228
229
230struct HorizontalConcatenateRD2<T> {
231  e0: Box<dyn CopyMat<T>>,
232  e1: Box<dyn CopyMat<T>>,
233  out: Ref<RowDVector<T>>,
234}
235impl<T> MechFunction for HorizontalConcatenateRD2<T>
236where
237  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
238  Ref<RowDVector<T>>: ToValue
239{
240  fn solve(&self) {
241    let mut offset = self.e0.copy_into_r(&self.out,0);
242    offset += self.e1.copy_into_r(&self.out,offset);
243  }
244  fn out(&self) -> Value { self.out.to_value() }
245  fn to_string(&self) -> String { format!("HorizontalConcatenateRD2\n{:#?}", self.out) }
246}
247
248struct HorizontalConcatenateRD3<T> {
249  e0: Box<dyn CopyMat<T>>,
250  e1: Box<dyn CopyMat<T>>,
251  e2: Box<dyn CopyMat<T>>,
252  out: Ref<RowDVector<T>>,
253}
254
255impl<T> MechFunction for HorizontalConcatenateRD3<T>
256where
257  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
258  Ref<RowDVector<T>>: ToValue
259{
260  fn solve(&self) {
261    let mut offset = self.e0.copy_into_r(&self.out,0);
262    offset += self.e1.copy_into_r(&self.out,offset);
263    self.e2.copy_into_r(&self.out,offset);
264  }
265  fn out(&self) -> Value { self.out.to_value() }
266  fn to_string(&self) -> String { format!("HorizontalConcatenateRD3\n{:#?}", self.out) }
267}
268
269struct HorizontalConcatenateRD4<T> {
270  e0: Box<dyn CopyMat<T>>,
271  e1: Box<dyn CopyMat<T>>,
272  e2: Box<dyn CopyMat<T>>,
273  e3: Box<dyn CopyMat<T>>,
274  out: Ref<RowDVector<T>>,
275}
276
277impl <T> MechFunction for HorizontalConcatenateRD4<T>
278where
279  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
280  Ref<RowDVector<T>>: ToValue
281{
282  fn solve(&self) {
283    let mut offset = self.e0.copy_into_r(&self.out,0);
284    offset += self.e1.copy_into_r(&self.out,offset);
285    offset += self.e2.copy_into_r(&self.out,offset);
286    self.e3.copy_into_r(&self.out,offset);
287  }
288  fn out(&self) -> Value { self.out.to_value() }
289  fn to_string(&self) -> String { format!("HorizontalConcatenateRD4\n{:#?}", self.out) }
290}
291
292struct HorizontalConcatenateRDN<T> {
293  scalar: Vec<(Ref<T>,usize)>,
294  matrix: Vec<(Box<dyn CopyMat<T>>,usize)>,
295  out: Ref<RowDVector<T>>,
296}
297
298impl<T> MechFunction for HorizontalConcatenateRDN<T> 
299where
300  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
301  Ref<RowDVector<T>>: ToValue
302{
303  fn solve(&self) {
304    unsafe {
305      let mut out_ptr = (&mut *(self.out.as_ptr()));
306      for (e,i) in &self.matrix {
307        let e0_ptr = e.copy_into_r(&self.out,*i);
308      }
309      for (e,i) in &self.scalar {
310        out_ptr[*i] = e.borrow().clone();
311      }
312    }
313  }
314  fn out(&self) -> Value { self.out.to_value() }
315  fn to_string(&self) -> String { format!("HorizontalConcatenateRDN\n{:#?}", self.out) }
316}
317
318#[derive(Debug)]
319struct HorizontalConcatenateS1<T> {
320  out: Ref<Matrix1<T>>,
321}
322
323impl<T> MechFunction for HorizontalConcatenateS1<T> 
324where
325  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
326  Ref<Matrix1<T>>: ToValue
327{
328  fn solve(&self) {}
329  fn out(&self) -> Value { self.out.to_value() }
330  fn to_string(&self) -> String { format!("{:#?}", self) }
331}
332
333horizontal_concatenate!(HorizontalConcatenateS2,2);
334horizontal_concatenate!(HorizontalConcatenateS3,3);
335horizontal_concatenate!(HorizontalConcatenateS4,4);
336horizontal_concatenate!(HorizontalConcatenateR2,2);
337horizontal_concatenate!(HorizontalConcatenateR3,3);
338horizontal_concatenate!(HorizontalConcatenateR4,4);
339
340#[derive(Debug)]
341struct HorizontalConcatenateSD<T> {
342  out: Ref<RowDVector<T>>,
343}
344impl<T> MechFunction for HorizontalConcatenateSD<T>
345where
346  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
347  Ref<RowDVector<T>>: ToValue
348{
349  fn solve(&self) { }
350  fn out(&self) -> Value { self.out.to_value() }
351  fn to_string(&self) -> String { format!("{:#?}", self) }
352}
353
354macro_rules! horzcat_single {
355  ($name:ident,$shape:ident) => {
356    #[derive(Debug)]
357    struct $name<T> {
358      out: Ref<$shape<T>>,
359    }
360    impl<T> MechFunction for $name<T>
361    where
362      T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
363      Ref<$shape<T>>: ToValue
364    {
365      fn solve(&self) { }
366      fn out(&self) -> Value { self.out.to_value() }
367      fn to_string(&self) -> String { format!("{:#?}", self) }
368    }
369  }
370}
371
372horzcat_single!(HorizontalConcatenateM1,Matrix1);
373horzcat_single!(HorizontalConcatenateM2,Matrix2);
374horzcat_single!(HorizontalConcatenateM3,Matrix3);
375horzcat_single!(HorizontalConcatenateM4,Matrix4);
376horzcat_single!(HorizontalConcatenateM2x3,Matrix2x3);
377horzcat_single!(HorizontalConcatenateM3x2,Matrix3x2);
378horzcat_single!(HorizontalConcatenateMD,DMatrix);
379horzcat_single!(HorizontalConcatenateV2,Vector2);
380horzcat_single!(HorizontalConcatenateV3,Vector3);
381horzcat_single!(HorizontalConcatenateV4,Vector4);
382horzcat_single!(HorizontalConcatenateVD,DVector);
383
384macro_rules! horzcat_sr2 {
385  ($out:expr, $e0:expr) => {
386    $out[1] = $e0[0].clone();
387    $out[2] = $e0[1].clone();
388  };
389}
390horzcat_one_arg!(HorizontalConcatenateSR2, RowVector2, RowVector3, horzcat_sr2);
391
392macro_rules! horzcat_r2s {
393  ($out:expr, $e0:expr) => {
394    $out[0] = $e0[0].clone();
395    $out[1] = $e0[1].clone();
396  };
397}
398horzcat_one_arg!(HorizontalConcatenateR2S, RowVector2, RowVector3, horzcat_r2s);
399
400macro_rules! horzcat_sm1 {
401  ($out:expr, $e0:expr) => {
402    $out[1] = $e0[0].clone();
403  };
404}
405horzcat_one_arg!(HorizontalConcatenateSM1, Matrix1, RowVector2, horzcat_sm1);
406
407macro_rules! horzcat_m1s {
408  ($out:expr, $e0:expr) => {
409    $out[0] = $e0[0].clone();
410  };
411}
412horzcat_one_arg!(HorizontalConcatenateM1S, Matrix1, RowVector2, horzcat_m1s);
413
414macro_rules! horzcat_sssm1 {
415  ($out:expr, $e0:expr) => {
416    $out[3] = $e0[0].clone();
417  };
418}
419horzcat_one_arg!(HorizontalConcatenateSSSM1, Matrix1, RowVector4, horzcat_sssm1);
420
421macro_rules! horzcat_ssm1s {
422  ($out:expr, $e0:expr) => {
423    $out[2] = $e0[0].clone();
424  };
425}
426horzcat_one_arg!(HorizontalConcatenateSSM1S, Matrix1, RowVector4, horzcat_ssm1s);
427
428macro_rules! horzcat_sm1ss {
429  ($out:expr, $e0:expr) => {
430    $out[1] = $e0[0].clone();
431  };
432}
433horzcat_one_arg!(HorizontalConcatenateSM1SS, Matrix1, RowVector4, horzcat_sm1ss);
434
435macro_rules! horzcat_m1sss {
436  ($out:expr, $e0:expr) => {
437    $out[0] = $e0[0].clone();
438  };
439}
440horzcat_one_arg!(HorizontalConcatenateM1SSS, Matrix1, RowVector4, horzcat_m1sss);
441
442macro_rules! horzcat_sr3 {
443  ($out:expr, $e0:expr) => {
444    $out[1] = $e0[0].clone();
445    $out[2] = $e0[1].clone();
446    $out[3] = $e0[2].clone();
447  };
448}
449horzcat_one_arg!(HorizontalConcatenateSR3, RowVector3, RowVector4, horzcat_sr3);
450
451macro_rules! horzcat_r3s {
452  ($out:expr, $e0:expr) => {
453    $out[0] = $e0[0].clone();
454    $out[1] = $e0[1].clone();
455    $out[2] = $e0[2].clone();
456  };
457}
458horzcat_one_arg!(HorizontalConcatenateR3S, RowVector3, RowVector4, horzcat_r3s);
459
460macro_rules! horzcat_ssm1 {
461  ($out:expr, $e0:expr) => {
462    $out[2] = $e0[0].clone();
463  };
464}
465horzcat_one_arg!(HorizontalConcatenateSSM1, Matrix1, RowVector3, horzcat_ssm1);
466
467macro_rules! horzcat_sm1s {
468  ($out:expr, $e0:expr) => {
469    $out[1] = $e0[0].clone();
470  };
471}
472horzcat_one_arg!(HorizontalConcatenateSM1S, Matrix1, RowVector3, horzcat_sm1s);
473
474macro_rules! horzcat_m1ss {
475  ($out:expr, $e0:expr) => {
476    $out[0] = $e0[0].clone();
477  };
478}
479horzcat_one_arg!(HorizontalConcatenateM1SS, Matrix1, RowVector3, horzcat_m1ss);
480
481macro_rules! horzcat_ssr2 {
482  ($out:expr, $e0:expr) => {
483    $out[2] = $e0[0].clone();
484    $out[3] = $e0[1].clone();
485  };
486}
487horzcat_one_arg!(HorizontalConcatenateSSR2, RowVector2, RowVector4, horzcat_ssr2);
488
489macro_rules! horzcat_sr2s {
490  ($out:expr, $e0:expr) => {
491    $out[1] = $e0[0].clone();
492    $out[2] = $e0[1].clone();
493  };
494}
495horzcat_one_arg!(HorizontalConcatenateSR2S, RowVector2, RowVector4, horzcat_sr2s);
496
497macro_rules! horzcat_r2ss {
498  ($out:expr, $e0:expr) => {
499    $out[0] = $e0[0].clone();
500    $out[1] = $e0[1].clone();
501  };
502}
503horzcat_one_arg!(HorizontalConcatenateR2SS, RowVector2, RowVector4, horzcat_r2ss);
504
505macro_rules! horzcat_m1m1s {
506  ($out:expr, $e0:expr, $e1:expr) => {
507    $out[0] = $e0[0].clone();
508    $out[1] = $e1[0].clone();
509  };}
510horzcat_two_args!(HorizontalConcatenateM1M1S,Matrix1,Matrix1,RowVector3,horzcat_m1m1s);
511
512macro_rules! horzcat_m1m1 {
513  ($out:expr, $e0:expr, $e1:expr) => {
514    $out[0] = $e0[0].clone();
515    $out[1] = $e1[0].clone();
516  };}
517horzcat_two_args!(HorizontalConcatenateM1M1,Matrix1,Matrix1,RowVector2,horzcat_m1m1);
518
519macro_rules! horzcat_m1sm1 {
520  ($out:expr, $e0:expr, $e1:expr) => {
521    $out[0] = $e0[0].clone();
522    $out[2] = $e1[0].clone();
523  };}
524horzcat_two_args!(HorizontalConcatenateM1SM1,Matrix1,Matrix1,RowVector3,horzcat_m1sm1);
525
526macro_rules! horzcat_sm1m1 {
527  ($out:expr, $e0:expr, $e1:expr) => {
528    $out[1] = $e0[0].clone();
529    $out[2] = $e1[0].clone();
530  };}
531horzcat_two_args!(HorizontalConcatenateSM1M1,Matrix1,Matrix1,RowVector3,horzcat_sm1m1);
532
533macro_rules! horzcat_r2r2 {
534  ($out:expr, $e0:expr, $e1:expr) => {
535    $out[0] = $e0[0].clone();
536    $out[1] = $e0[1].clone();
537    $out[2] = $e1[0].clone();
538    $out[3] = $e1[1].clone();
539  };}
540horzcat_two_args!(HorizontalConcatenateR2R2,RowVector2,RowVector2,RowVector4,horzcat_r2r2);
541
542macro_rules! horzcat_m1r3 {
543  ($out:expr, $e0:expr, $e1:expr) => {
544    $out[0] = $e0[0].clone();
545    $out[1] = $e1[0].clone();
546    $out[2] = $e1[1].clone();
547    $out[3] = $e1[2].clone();
548  };}
549horzcat_two_args!(HorizontalConcatenateM1R3,Matrix1,RowVector3,RowVector4,horzcat_m1r3);
550
551macro_rules! horzcat_r3m1 {
552  ($out:expr, $e0:expr, $e1:expr) => {
553    $out[0] = $e0[0].clone();
554    $out[1] = $e0[1].clone();
555    $out[2] = $e0[2].clone();
556    $out[3] = $e1[0].clone();
557  };}
558horzcat_two_args!(HorizontalConcatenateR3M1,RowVector3,Matrix1,RowVector4,horzcat_r3m1);
559
560macro_rules! horzcat_sm1r2 {
561  ($out:expr, $e0:expr, $e1:expr) => {
562    $out[1] = $e0[0].clone();
563    $out[2] = $e1[0].clone();
564    $out[3] = $e1[1].clone();
565  };}
566horzcat_two_args!(HorizontalConcatenateSM1R2,Matrix1,RowVector2,RowVector4,horzcat_sm1r2);
567
568macro_rules! horzcat_m1sr2 {
569  ($out:expr, $e0:expr, $e1:expr) => {
570    $out[0] = $e0[0].clone();
571    $out[2] = $e1[0].clone();
572    $out[3] = $e1[1].clone();
573  };}
574horzcat_two_args!(HorizontalConcatenateM1SR2,Matrix1,RowVector2,RowVector4,horzcat_m1sr2);
575  
576macro_rules! horzcat_sm1sm1 {
577  ($out:expr, $e0:expr, $e1:expr) => {
578    $out[1] = $e0[0].clone();
579    $out[3] = $e1[0].clone();
580  };} 
581horzcat_two_args!(HorizontalConcatenateSM1SM1,Matrix1,Matrix1,RowVector4,horzcat_sm1sm1);
582
583macro_rules! horzcat_m1r2s {
584  ($out:expr, $e0:expr, $e1:expr) => {
585    $out[0] = $e0[0].clone();
586    $out[1] = $e1[0].clone();
587    $out[2] = $e1[1].clone();
588  };} 
589horzcat_two_args!(HorizontalConcatenateM1R2S,Matrix1,RowVector2,RowVector4,horzcat_m1r2s);
590
591macro_rules! horzcat_r2m1s {
592  ($out:expr, $e0:expr, $e1:expr) => {
593    $out[0] = $e0[0].clone();
594    $out[1] = $e0[1].clone();
595    $out[2] = $e1[0].clone();
596  };} 
597horzcat_two_args!(HorizontalConcatenateR2M1S,RowVector2,Matrix1,RowVector4,horzcat_r2m1s);
598
599macro_rules! horzcat_r2sm1 {
600  ($out:expr, $e0:expr, $e1:expr) => {
601    $out[0] = $e0[0].clone();
602    $out[1] = $e0[1].clone();
603    $out[3] = $e1[0].clone();
604  };
605}
606horzcat_two_args!(HorizontalConcatenateR2SM1, RowVector2, Matrix1, RowVector4, horzcat_r2sm1);
607
608macro_rules! horzcat_sr2m1 {
609  ($out:expr, $e0:expr, $e1:expr) => {
610    $out[1] = $e0[0].clone();
611    $out[2] = $e0[1].clone();
612    $out[3] = $e1[0].clone();
613  };
614}
615horzcat_two_args!(HorizontalConcatenateSR2M1, RowVector2, Matrix1, RowVector4, horzcat_sr2m1);
616
617macro_rules! horzcat_ssm1m1 {
618  ($out:expr, $e0:expr, $e1:expr) => {
619    $out[2] = $e0[0].clone();
620    $out[3] = $e1[0].clone();
621  };
622}
623horzcat_two_args!(HorizontalConcatenateSSM1M1, Matrix1, Matrix1, RowVector4, horzcat_ssm1m1);
624
625macro_rules! horzcat_m1m1ss {
626  ($out:expr, $e0:expr, $e1:expr) => {
627    $out[0] = $e0[0].clone();
628    $out[1] = $e1[0].clone();
629  };
630}
631horzcat_two_args!(HorizontalConcatenateM1M1SS, Matrix1, Matrix1, RowVector4, horzcat_m1m1ss);
632
633macro_rules! horzcat_sm1m1s {
634  ($out:expr, $e0:expr, $e1:expr) => {
635    $out[1] = $e0[0].clone();
636    $out[2] = $e1[0].clone();
637  };
638}
639horzcat_two_args!(HorizontalConcatenateSM1M1S, Matrix1, Matrix1, RowVector4, horzcat_sm1m1s);
640
641macro_rules! horzcat_m1ssm1 {
642  ($out:expr, $e0:expr, $e1:expr) => {
643    $out[0] = $e0[0].clone();
644    $out[3] = $e1[0].clone();
645  };
646}
647horzcat_two_args!(HorizontalConcatenateM1SSM1, Matrix1, Matrix1, RowVector4, horzcat_m1ssm1);
648
649macro_rules! horzcat_m1sm1s {
650  ($out:expr, $e0:expr, $e1:expr) => {
651    $out[0] = $e0[0].clone();
652    $out[2] = $e1[0].clone();
653  };
654}
655horzcat_two_args!(HorizontalConcatenateM1SM1S, Matrix1, Matrix1, RowVector4, horzcat_m1sm1s);
656
657macro_rules! horzcat_m1r2 {
658  ($out:expr, $e0:expr, $e1:expr) => {
659    $out[0] = $e0[0].clone();
660    $out[1] = $e1[0].clone();
661    $out[2] = $e1[1].clone();
662  };
663}
664horzcat_two_args!(HorizontalConcatenateM1R2, Matrix1, RowVector2, RowVector3, horzcat_m1r2);
665
666macro_rules! horzcat_r2m1 {
667  ($out:expr, $e0:expr, $e1:expr) => {
668    $out[0] = $e0[0].clone();
669    $out[1] = $e0[1].clone();
670    $out[2] = $e1[0].clone();
671  };
672}
673horzcat_two_args!(HorizontalConcatenateR2M1, RowVector2, Matrix1, RowVector3, horzcat_r2m1);
674
675macro_rules! horzcat_m1m1m1 {
676  ($out:expr, $e0:expr,$e1:expr,$e2:expr) => {
677    $out[0] = $e0[0].clone();
678    $out[1] = $e1[0].clone();
679    $out[2] = $e2[0].clone();
680  };
681}
682horzcat_three_args!(HorizontalConcatenateM1M1M1,Matrix1,Matrix1,Matrix1,RowVector3, horzcat_m1m1m1);
683
684macro_rules! horzcat_m1m1r2 {
685  ($out:expr, $e0:expr, $e1:expr, $e2:expr) => {
686    $out[0] = $e0[0].clone();
687    $out[1] = $e1[0].clone();
688    $out[2] = $e2[0].clone();
689    $out[3] = $e2[1].clone();
690  };
691}
692horzcat_three_args!(HorizontalConcatenateM1M1R2, Matrix1, Matrix1, RowVector2, RowVector4, horzcat_m1m1r2);
693
694macro_rules! horzcat_m1r2m1 {
695  ($out:expr, $e0:expr, $e1:expr, $e2:expr) => {
696    $out[0] = $e0[0].clone();
697    $out[1] = $e1[0].clone();
698    $out[2] = $e1[1].clone();
699    $out[3] = $e2[0].clone();
700  };
701}
702horzcat_three_args!(HorizontalConcatenateM1R2M1, Matrix1, RowVector2, Matrix1, RowVector4, horzcat_m1r2m1);
703
704macro_rules! horzcat_r2m1m1 {
705  ($out:expr, $e0:expr, $e1:expr, $e2:expr) => {
706    $out[0] = $e0[0].clone();
707    $out[1] = $e0[1].clone();
708    $out[2] = $e1[0].clone();
709    $out[3] = $e2[0].clone();
710  };
711}
712horzcat_three_args!(HorizontalConcatenateR2M1M1, RowVector2, Matrix1, Matrix1, RowVector4, horzcat_r2m1m1);
713
714macro_rules! horzcat_sm1m1m1 {
715  ($out:expr, $e0:expr, $e1:expr, $e2:expr) => {
716    $out[1] = $e0[0].clone();
717    $out[2] = $e1[0].clone();
718    $out[3] = $e2[0].clone();
719  };
720}
721horzcat_three_args!(HorizontalConcatenateSM1M1M1, Matrix1, Matrix1, Matrix1, RowVector4, horzcat_sm1m1m1);
722
723macro_rules! horzcat_m1sm1m1 {
724  ($out:expr, $e0:expr, $e1:expr, $e2:expr) => {
725    $out[0] = $e0[0].clone();
726    $out[2] = $e1[0].clone();
727    $out[3] = $e2[0].clone();
728  };
729}
730horzcat_three_args!(HorizontalConcatenateM1SM1M1, Matrix1, Matrix1, Matrix1, RowVector4, horzcat_m1sm1m1);
731
732macro_rules! horzcat_m1m1sm1 {
733  ($out:expr, $e0:expr, $e1:expr, $e2:expr) => {
734    $out[0] = $e0[0].clone();
735    $out[1] = $e1[0].clone();
736    $out[3] = $e2[0].clone();
737  };
738}
739horzcat_three_args!(HorizontalConcatenateM1M1SM1, Matrix1, Matrix1, Matrix1, RowVector4, horzcat_m1m1sm1);
740
741macro_rules! horzcat_m1m1m1s {
742  ($out:expr, $e0:expr, $e1:expr, $e2:expr) => {
743    $out[0] = $e0[0].clone();
744    $out[1] = $e1[0].clone();
745    $out[2] = $e2[0].clone();
746  };
747}
748horzcat_three_args!(HorizontalConcatenateM1M1M1S, Matrix1, Matrix1, Matrix1, RowVector4, horzcat_m1m1m1s);
749
750#[derive(Debug)]
751struct HorizontalConcatenateM1M1M1M1<T> {
752  e0: Ref<Matrix1<T>>,
753  e1: Ref<Matrix1<T>>,
754  e2: Ref<Matrix1<T>>,
755  e3: Ref<Matrix1<T>>,
756  out: Ref<RowVector4<T>>,
757}
758impl<T> MechFunction for HorizontalConcatenateM1M1M1M1<T>
759where
760  T: Copy + Debug + Clone + Sync + Send + PartialEq + 'static,
761  Ref<RowVector4<T>>: ToValue
762{
763  fn solve(&self) { 
764    unsafe {
765      let e0_ptr = (*(self.e0.as_ptr())).clone();
766      let e1_ptr = (*(self.e1.as_ptr())).clone();
767      let e2_ptr = (*(self.e2.as_ptr())).clone();
768      let e3_ptr = (*(self.e3.as_ptr())).clone();
769      let mut out_ptr = (&mut *(self.out.as_ptr()));
770      out_ptr[0] = e0_ptr[0].clone();
771      out_ptr[1] = e1_ptr[0].clone();
772      out_ptr[2] = e2_ptr[0].clone();
773      out_ptr[3] = e3_ptr[0].clone();
774    }
775  }
776  fn out(&self) -> Value { self.out.to_value() }
777  fn to_string(&self) -> String { format!("{:#?}", self) }
778}
779
780macro_rules! horzcat_v2v2 {
781  ($out:expr, $e0:expr, $e1:expr) => {
782    $out[0] = $e0[0].clone();
783    $out[1] = $e0[1].clone();
784    $out[2] = $e1[0].clone();
785    $out[3] = $e1[1].clone();
786  };
787}
788horzcat_two_args!(HorizontalConcatenateV2V2, Vector2, Vector2, Matrix2, horzcat_v2v2);
789
790macro_rules! horzcat_v3v3 {
791  ($out:expr, $e0:expr, $e1:expr) => {
792    $out[0] = $e0[0].clone();
793    $out[1] = $e0[1].clone();
794    $out[2] = $e0[2].clone();
795    $out[3] = $e1[0].clone();
796    $out[4] = $e1[1].clone();
797    $out[5] = $e1[2].clone();
798  };
799}
800horzcat_two_args!(HorizontalConcatenateV3V3, Vector3, Vector3, Matrix3x2, horzcat_v3v3);
801
802macro_rules! horzcat_v2m2 {
803  ($out:expr, $e0:expr, $e1:expr) => {
804    $out[0] = $e0[0].clone();
805    $out[1] = $e0[1].clone();
806    $out[2] = $e1[0].clone();
807    $out[3] = $e1[1].clone();
808    $out[4] = $e1[2].clone();
809    $out[5] = $e1[3].clone();
810  };
811}
812horzcat_two_args!(HorizontalConcatenateV2M2, Vector2, Matrix2, Matrix2x3, horzcat_v2m2);
813
814macro_rules! horzcat_m2v2 {
815  ($out:expr, $e0:expr, $e1:expr) => {
816    $out[0] = $e0[0].clone();
817    $out[1] = $e0[1].clone();
818    $out[2] = $e0[2].clone();
819    $out[3] = $e0[3].clone();
820    $out[4] = $e1[0].clone();
821    $out[5] = $e1[1].clone();
822  };
823}
824horzcat_two_args!(HorizontalConcatenateM2V2, Matrix2, Vector2, Matrix2x3, horzcat_m2v2);
825
826macro_rules! horzcat_m3x2v3 {
827  ($out:expr, $e0:expr, $e1:expr) => {
828    $out[0] = $e0[0].clone();
829    $out[1] = $e0[1].clone();
830    $out[2] = $e0[2].clone();
831    $out[3] = $e0[3].clone();
832    $out[4] = $e0[4].clone();
833    $out[5] = $e0[5].clone();
834    $out[6] = $e1[0].clone();
835    $out[7] = $e1[1].clone();
836    $out[8] = $e1[2].clone();
837  };
838}
839horzcat_two_args!(HorizontalConcatenateM3x2V3, Matrix3x2, Vector3, Matrix3, horzcat_m3x2v3);
840
841macro_rules! horzcat_v3m3x2 {
842  ($out:expr, $e0:expr, $e1:expr) => {
843    $out[0] = $e0[0].clone();
844    $out[1] = $e0[1].clone();
845    $out[2] = $e0[2].clone();
846    $out[3] = $e1[0].clone();
847    $out[4] = $e1[1].clone();
848    $out[5] = $e1[2].clone();
849    $out[6] = $e1[3].clone();
850    $out[7] = $e1[4].clone();
851    $out[8] = $e1[5].clone();
852  };
853}
854horzcat_two_args!(HorizontalConcatenateV3M3x2, Vector3, Matrix3x2, Matrix3, horzcat_v3m3x2);
855
856macro_rules! horzcat_v4md {
857  ($out:expr, $e0:expr, $e1:expr) => {
858    $out[0] = $e0[0].clone();
859    $out[1] = $e0[1].clone();
860    $out[2] = $e0[2].clone();
861    $out[3] = $e0[3].clone();
862    let offset = 4;
863    for i in 0..$e1.len() {
864      $out[i + offset] = $e1[i].clone();
865    }
866  };
867}
868horzcat_two_args!(HorizontalConcatenateV4MD, Vector4, DMatrix, Matrix4, horzcat_v4md);
869
870macro_rules! horzcat_mdv4 {
871  ($out:expr, $e0:expr, $e1:expr) => {
872    let e0_len = $e0.len();
873    for i in 0..e0_len {
874      $out[i] = $e0[i].clone();
875    }
876    let offset = e0_len;
877    $out[offset] = $e1[0].clone();
878    $out[offset + 1] = $e1[1].clone();
879    $out[offset + 2] = $e1[2].clone();
880    $out[offset + 3] = $e1[3].clone();
881  };
882}
883horzcat_two_args!(HorizontalConcatenateMDV4, DMatrix, Vector4, Matrix4, horzcat_mdv4);
884
885macro_rules! horzcat_mdmd {
886  ($out:expr, $e0:expr, $e1:expr) => {
887    let e0_len = $e0.len();
888    for i in 0..e0_len {
889      $out[i] = $e0[i].clone();
890    }
891    let offset = e0_len;
892    for i in 0..$e1.len() {
893      $out[i + offset] = $e1[i].clone();
894    }
895  };
896}
897horzcat_two_args!(HorizontalConcatenateMDMD, DMatrix, DMatrix, Matrix4, horzcat_mdmd);
898
899macro_rules! horzcat_mdmdmd {
900  ($out:expr, $e0:expr, $e1:expr, $e2:expr) => {
901    let e0_len = $e0.len();
902    for i in 0..e0_len {
903      $out[i] = $e0[i].clone();
904    }
905    let offset = e0_len;
906    for i in 0..$e1.len() {
907      $out[i + offset] = $e1[i].clone();
908    }
909    let offset = offset + $e1.len();
910    for i in 0..$e2.len() {
911      $out[i + offset] = $e2[i].clone();
912    }
913  };
914}
915
916horzcat_three_args!(HorizontalConcatenateV2V2V2, Vector2, Vector2, Vector2, Matrix2x3, horzcat_mdmdmd);
917horzcat_three_args!(HorizontalConcatenateV3V3V3, Vector3, Vector3, Vector3, Matrix3, horzcat_mdmdmd);
918horzcat_three_args!(HorizontalConcatenateV4V4MD, Vector4, Vector4, DMatrix, Matrix4, horzcat_mdmdmd);
919horzcat_three_args!(HorizontalConcatenateV4MDV4, Vector4, DMatrix, Vector4, Matrix4, horzcat_mdmdmd);
920horzcat_three_args!(HorizontalConcatenateMDV4V4, DMatrix, Vector4, Vector4, Matrix4, horzcat_mdmdmd);
921
922
923macro_rules! horzcat_mdmdmdmd {
924  ($out:expr, $e0:expr, $e1:expr, $e2:expr, $e3:expr) => {
925    let e0_len = $e0.len();
926    for i in 0..e0_len {
927      $out[i] = $e0[i].clone();
928    }
929    let offset = e0_len;
930    for i in 0..$e1.len() {
931      $out[i + offset] = $e1[i].clone();
932    }
933    let offset = offset + $e1.len();
934    for i in 0..$e2.len() {
935      $out[i + offset] = $e2[i].clone();
936    }
937    let offset = offset + $e2.len();
938    for i in 0..$e3.len() {
939      $out[i + offset] = $e3[i].clone();
940    }
941  };
942}
943
944horzcat_four_args!(HorizontalConcatenateV4V4V4V4, Vector4, Vector4, Vector4, Vector4, Matrix4, horzcat_mdmdmdmd);
945
946macro_rules! impl_horzcat_arms {
947  ($kind:ident, $args:expr, $default:expr) => {
948    paste!{
949    {
950      let arguments = $args;   
951      let rows = arguments[0].shape()[0];
952      let columns:usize = arguments.iter().fold(0, |acc, x| acc + x.shape()[1]);
953      let rows:usize = arguments[0].shape()[0];
954      let nargs = arguments.len();
955      let kinds: Vec<ValueKind> = arguments.iter().map(|x| x.kind()).collect::<Vec<ValueKind>>();
956      let no_refs = !kinds.iter().any(|x| {
957        match x {
958          ValueKind::Reference(_) => true,
959          _ => false,
960      }});
961      if no_refs {
962        let mat: Vec<$kind> = arguments.iter().flat_map(|v| v.[<as_vec $kind:lower>]().unwrap()).collect::<Vec<$kind>>();
963        match &mat[..] {
964          [e0]             => {return Ok(Box::new(HorizontalConcatenateS1{out:new_ref(Matrix1::from_vec(mat))}));}
965          [e0, e1]         => {return Ok(Box::new(HorizontalConcatenateS2{out:new_ref(RowVector2::from_vec(mat))}));}
966          [e0, e1, e2]     => {return Ok(Box::new(HorizontalConcatenateS3{out:new_ref(RowVector3::from_vec(mat))}));}
967          [e0, e1, e2, e3] => {return Ok(Box::new(HorizontalConcatenateS4{out:new_ref(RowVector4::from_vec(mat))}));}
968          _ => {return Ok(Box::new(HorizontalConcatenateSD{out:new_ref(RowDVector::from_vec(mat))}));}
969        }      
970      } else {
971        match (nargs,rows,columns) {
972          #[cfg(feature = "Matrix1")]
973          (1,1,1) => {
974            let mut out = Matrix1::from_element($default);
975            match &arguments[..] {
976              // m1
977              [Value::MutableReference(e0)] => {
978                match *e0.borrow() {
979                  Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)) => {
980                    return Ok(Box::new(HorizontalConcatenateM1{out: e0.clone()}));
981                  }
982                  _ => todo!(),
983                }
984              }
985              _ => todo!(),
986            }
987          }
988          #[cfg(feature = "RowVector2")]
989          (1,1,2) => {
990            let mut out = RowVector2::from_element($default);
991            match &arguments[..] {
992              // r2
993              [Value::MutableReference(e0)] => {
994                match *e0.borrow() {
995                  Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e0)) => {
996                    return Ok(Box::new(HorizontalConcatenateR2{out: e0.clone()}));
997                  }
998                  _ => todo!(),
999                }
1000              }
1001              _ => todo!(),
1002            }
1003          }
1004          #[cfg(feature = "RowVector3")]
1005          (1,1,3) => {
1006            let mut out = RowVector3::from_element($default);
1007            match &arguments[..] {
1008              // r3
1009              [Value::MutableReference(e0)] => {
1010                match *e0.borrow() {
1011                  Value::[<Matrix $kind:camel>](Matrix::RowVector3(ref e0)) => {
1012                    return Ok(Box::new(HorizontalConcatenateR3{out: e0.clone()}));
1013                  }
1014                  _ => todo!(),
1015                }
1016              }
1017              _ => todo!(),
1018            }
1019          }
1020          #[cfg(feature = "RowVector4")]
1021          (1,1,4) => {
1022            let mut out = RowVector4::from_element($default);
1023            match &arguments[..] {
1024              // r4
1025              [Value::MutableReference(e0)] => {
1026                match *e0.borrow() {
1027                  Value::[<Matrix $kind:camel>](Matrix::RowVector4(ref e0)) => {
1028                    return Ok(Box::new(HorizontalConcatenateR4{out: e0.clone()}));
1029                  }
1030                  _ => todo!(),
1031                }
1032              }
1033              _ => todo!(),
1034            }
1035          }
1036          #[cfg(feature = "RowVectorD")]
1037          (1,1,n) => {
1038            let mut out = RowVector4::from_element($default);
1039            match &arguments[..] {
1040              // rd
1041              [Value::MutableReference(e0)] => {
1042                match *e0.borrow() {
1043                  Value::[<Matrix $kind:camel>](Matrix::RowDVector(ref e0)) => {
1044                    return Ok(Box::new(HorizontalConcatenateRD{out: e0.clone()}));
1045                  }
1046                  _ => todo!(),
1047                }
1048              }
1049              _ => todo!(),
1050            }
1051          }
1052          #[cfg(feature = "RowVector2")]
1053          (2,1,2) => {
1054            let mut out = RowVector2::from_element($default);
1055            match &arguments[..] {
1056              // s1m1
1057              [Value::[<$kind:camel>](e0), Value::MutableReference(e1)] => {
1058                match *e1.borrow() {
1059                  Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)) => {
1060                    out[0] = e0.borrow().clone();
1061                    return Ok(Box::new(HorizontalConcatenateSM1{e0: e1.clone(), out: new_ref(out)}));
1062                  }
1063                  Value::[<$kind:camel>](ref e1) => {
1064                    out[0] = e0.borrow().clone();
1065                    out[1] = e1.borrow().clone();
1066                    return Ok(Box::new(HorizontalConcatenateR2{out: new_ref(out)}));
1067                  }
1068                  _ => todo!(),
1069                }
1070              }
1071              // m1s1
1072              [Value::MutableReference(e0), Value::[<$kind:camel>](e1)] => {
1073                match *e0.borrow() {
1074                  Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)) => {
1075                    out[1] = e1.borrow().clone();
1076                    return Ok(Box::new(HorizontalConcatenateM1S{e0: e0.clone(), out: new_ref(out)}));
1077                  }
1078                  Value::[<$kind:camel>](ref e0) => {
1079                    out[0] = e0.borrow().clone();
1080                    out[1] = e1.borrow().clone();
1081                    return Ok(Box::new(HorizontalConcatenateR2{out: new_ref(out)}));
1082                  }
1083                  _ => todo!(),
1084                }
1085              }              
1086              // m1m1
1087              [Value::MutableReference(e0), Value::MutableReference(e1)] => {
1088                match (e0.borrow().clone(), e1.borrow().clone()) {
1089                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1))) => {
1090                    return Ok(Box::new(HorizontalConcatenateM1M1{e0: e0.clone(), e1: e1.clone(), out: new_ref(out)}));
1091                  }
1092                  (Value::[<$kind:camel>](ref e0),Value::[<$kind:camel>](ref e1)) => {
1093                    out[0] = e0.borrow().clone();
1094                    out[1] = e1.borrow().clone();
1095                    return Ok(Box::new(HorizontalConcatenateR2{out: new_ref(out)}));
1096                  }
1097                  _ => todo!(),
1098                }
1099              }      
1100              _ => todo!(),
1101            }
1102          }
1103          #[cfg(feature = "RowVector3")]
1104          (2,1,3) => {
1105            let mut out = RowVector3::from_element($default);
1106            match &arguments[..] {
1107              //sr2
1108              [Value::[<$kind:camel>](e0), Value::MutableReference(e1)] => {
1109                match *e1.borrow() {
1110                  Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e1)) => {
1111                    out[0] = e0.borrow().clone();
1112                    return Ok(Box::new(HorizontalConcatenateSR2{e0: e1.clone(), out: new_ref(out)}));
1113                  }
1114                  _ => todo!(),
1115                }
1116              }
1117              //r2s
1118              [Value::MutableReference(e0),Value::[<$kind:camel>](e1)] => {
1119                match *e0.borrow() {
1120                  Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e0)) => {
1121                    out[2] = e1.borrow().clone();
1122                    return Ok(Box::new(HorizontalConcatenateR2S{e0: e0.clone(), out: new_ref(out)}));
1123                  }
1124                  _ => todo!(),
1125                }
1126              }
1127              [Value::MutableReference(e0),Value::MutableReference(e1)] => {
1128                match (&*e0.borrow(),&*e1.borrow()) {
1129                  //m1r2
1130                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e1))) => {
1131                    return Ok(Box::new(HorizontalConcatenateM1R2{e0: e0.clone(), e1: e1.clone(), out: new_ref(out)}));
1132                  }
1133                  //r2m1
1134                  (Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1))) => {
1135                    return Ok(Box::new(HorizontalConcatenateR2M1{e0: e0.clone(), e1: e1.clone(), out: new_ref(out)}));
1136                  }
1137                  _ => todo!(),
1138                }
1139              }
1140              _ => todo!(),
1141            }
1142          }
1143          #[cfg(feature = "RowVector4")]
1144          (2,1,4) => {
1145            let mut out = RowVector4::from_element($default);
1146            match &arguments[..] {
1147              // s r3
1148              [Value::[<$kind:camel>](e0), Value::MutableReference(e1)] => {
1149                match *e1.borrow() {
1150                  Value::[<Matrix $kind:camel>](Matrix::RowVector3(ref e1)) => {
1151                    out[0] = e0.borrow().clone();
1152                    return Ok(Box::new(HorizontalConcatenateSR3{e0: e1.clone(), out: new_ref(out)}));
1153                  }
1154                  _ => todo!(),
1155                }
1156              }
1157              // r3 s
1158              [Value::MutableReference(e0),Value::[<$kind:camel>](e1)] => {
1159                match *e0.borrow() {
1160                  Value::[<Matrix $kind:camel>](Matrix::RowVector3(ref e0)) => {
1161                    out[3] = e1.borrow().clone();
1162                    return Ok(Box::new(HorizontalConcatenateR3S{e0: e0.clone(), out: new_ref(out)}));
1163                  }
1164                  _ => todo!(),
1165                }
1166              }
1167              [Value::MutableReference(e0),Value::MutableReference(e1)] => {
1168                match (&*e0.borrow(),&*e1.borrow()) {
1169                  // m1 r3
1170                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),Value::[<Matrix $kind:camel>](Matrix::RowVector3(ref e1))) => {
1171                    return Ok(Box::new(HorizontalConcatenateM1R3{e0: e0.clone(), e1: e1.clone(), out: new_ref(out)}));
1172                  }
1173                  // r3 m1
1174                  (Value::[<Matrix $kind:camel>](Matrix::RowVector3(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1))) => {
1175                    return Ok(Box::new(HorizontalConcatenateR3M1{e0: e0.clone(), e1: e1.clone(), out: new_ref(out)}));
1176                  }
1177                  // r2 r2
1178                  (Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e0)),Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e1))) => {
1179                    return Ok(Box::new(HorizontalConcatenateR2R2{e0: e0.clone(), e1: e1.clone(), out: new_ref(out)}));
1180                  }
1181                  _ => todo!(),
1182                }
1183              }
1184              _ => todo!(),
1185            }
1186          } 
1187          #[cfg(feature = "RowVectorD")]
1188          (2,1,n) => {
1189            let mut out = RowDVector::from_element(n,$default);
1190            match &arguments[..] {
1191              [Value::MutableReference(e0),Value::MutableReference(e1)] => {
1192                match (&*e0.borrow(),&*e1.borrow()) {
1193                  (Value::[<Matrix $kind:camel>](e0),Value::[<Matrix $kind:camel>](e1)) => {
1194                    let e0 = e0.get_copyable_matrix();
1195                    let e1 = e1.get_copyable_matrix();
1196                    return Ok(Box::new(HorizontalConcatenateRD2{e0: e0, e1: e1, out: new_ref(out)}));
1197                  }
1198                  _ => todo!(),
1199                }
1200              }
1201              _ => todo!(),
1202            }
1203          }
1204          #[cfg(feature = "RowVector3")]
1205          (3,1,3) => {  
1206            let mut out = RowVector3::from_element($default);
1207            match &arguments[..] {
1208              // s s m1
1209              [Value::[<$kind:camel>](e0), Value::[<$kind:camel>](e1), Value::MutableReference(e2)] => {
1210                match *e2.borrow() {
1211                  Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2)) => {
1212                    out[0] = e0.borrow().clone();
1213                    out[1] = e1.borrow().clone();
1214                    return Ok(Box::new(HorizontalConcatenateSSM1{e0: e2.clone(), out: new_ref(out)}));
1215                  }
1216                  _ => todo!(),
1217                }
1218              }
1219              // s m1 s
1220              [Value::[<$kind:camel>](e0), Value::MutableReference(e1), Value::[<$kind:camel>](e2)] => {
1221                match *e1.borrow() {
1222                  Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)) => {
1223                    out[0] = e0.borrow().clone();
1224                    out[2] = e2.borrow().clone();
1225                    return Ok(Box::new(HorizontalConcatenateSM1S{e0: e1.clone(), out: new_ref(out)}));
1226                  }
1227                  _ => todo!(),
1228                }
1229              }
1230              // m1 s s
1231              [Value::MutableReference(e0), Value::[<$kind:camel>](e1), Value::[<$kind:camel>](e2)] => {
1232                match *e0.borrow() {
1233                  Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)) => {
1234                    out[1] = e1.borrow().clone();
1235                    out[2] = e2.borrow().clone();
1236                    return Ok(Box::new(HorizontalConcatenateM1SS{e0: e0.clone(), out: new_ref(out)}));
1237                  }
1238                  _ => todo!(),
1239                }
1240              }
1241              // m1 m1 s
1242              [Value::MutableReference(e0), Value::MutableReference(e1), Value::[<$kind:camel>](e2)] => {
1243                match (e0.borrow().clone(), e1.borrow().clone()) {
1244                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)), Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1))) => {
1245                    out[2] = e2.borrow().clone();
1246                    return Ok(Box::new(HorizontalConcatenateM1M1S{e0: e0.clone(), e1: e1.clone(), out: new_ref(out)}));
1247                  }
1248                  _ => todo!(),
1249                }
1250              }
1251              // m1 s m1
1252              [Value::MutableReference(e0), Value::[<$kind:camel>](e1), Value::MutableReference(e2)] => {
1253                match (e0.borrow().clone(), e2.borrow().clone()) {
1254                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)), Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1255                    out[1] = e1.borrow().clone();
1256                    return Ok(Box::new(HorizontalConcatenateM1SM1{e0: e0.clone(), e1: e2.clone(), out: new_ref(out)}));
1257                  }
1258                  _ => todo!(),
1259                }
1260              }
1261              // s m1 m1
1262              [Value::[<$kind:camel>](e0), Value::MutableReference(e1), Value::MutableReference(e2)] => {
1263                match (e1.borrow().clone(), e2.borrow().clone()) {
1264                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)), Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1265                    out[0] = e0.borrow().clone();
1266                    return Ok(Box::new(HorizontalConcatenateSM1M1{e0: e1.clone(), e1: e2.clone(), out: new_ref(out)}));
1267                  }
1268                  _ => todo!(),
1269                }
1270              }    
1271              // m1 m1 m1
1272              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2)] => {
1273                match (e0.borrow().clone(), e1.borrow().clone(), e2.borrow().clone()) {
1274                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)), Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)), Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1275                    return Ok(Box::new(HorizontalConcatenateM1M1M1{e0: e1.clone(), e1: e1.clone(), e2: e2.clone(), out: new_ref(out)}));
1276                  }
1277                  _ => todo!(),
1278                }
1279              }           
1280              _ => todo!()
1281            }
1282          }
1283          #[cfg(feature = "RowVector4")]
1284          (3,1,4) => {
1285            let mut out = RowVector4::from_element($default);
1286            match &arguments[..] {
1287              // s s r2
1288              [Value::[<$kind:camel>](e0), Value::[<$kind:camel>](e1), Value::MutableReference(e2)] => {
1289                match *e2.borrow() {
1290                  Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e2)) => {
1291                    out[0] = e0.borrow().clone();
1292                    out[1] = e1.borrow().clone();
1293                    return Ok(Box::new(HorizontalConcatenateSSR2{e0: e2.clone(), out: new_ref(out)}));
1294                  }
1295                  _ => todo!(),
1296                }
1297              }
1298              // s r2 s1
1299              [Value::[<$kind:camel>](e0), Value::MutableReference(e1), Value::[<$kind:camel>](e2)] => {
1300                match *e1.borrow() {
1301                  Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e1)) => {
1302                    out[0] = e0.borrow().clone();
1303                    out[3] = e2.borrow().clone();
1304                    return Ok(Box::new(HorizontalConcatenateSR2S{e0: e1.clone(), out: new_ref(out)}));
1305                  }
1306                  _ => todo!(),
1307                }
1308              }      
1309              // r2 s s
1310              [Value::MutableReference(e0), Value::[<$kind:camel>](e1), Value::[<$kind:camel>](e2)] => {
1311                match *e0.borrow() {
1312                  Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e0)) => {
1313                    out[2] = e1.borrow().clone();
1314                    out[3] = e2.borrow().clone();
1315                    return Ok(Box::new(HorizontalConcatenateR2SS{e0: e0.clone(), out: new_ref(out)}));
1316                  }
1317                  _ => todo!(),
1318                }
1319              }    
1320              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2)] => {
1321                match (e0.borrow().clone(),e1.borrow().clone(),e2.borrow().clone()) {
1322                  // m1 m1 r2
1323                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),
1324                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)),
1325                   Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e2))) => {
1326                    return Ok(Box::new(HorizontalConcatenateM1M1R2{e0: e0.clone(), e1: e1.clone(), e2: e2.clone(), out: new_ref(out)}));
1327                  }
1328                  // m1 r2 m1
1329                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),
1330                   Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e1)),
1331                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1332                    return Ok(Box::new(HorizontalConcatenateM1R2M1{e0: e0.clone(), e1: e1.clone(), e2: e2.clone(), out: new_ref(out)}));
1333                  }
1334                  // r2 m1 m1
1335                  (Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e0)),
1336                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)),
1337                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1338                    return Ok(Box::new(HorizontalConcatenateR2M1M1{e0: e0.clone(), e1: e1.clone(), e2: e2.clone(), out: new_ref(out)}));
1339                  }
1340                  _ => todo!(),
1341                }
1342              }        
1343              [Value::[<$kind:camel>](e0), Value::MutableReference(e1), Value::MutableReference(e2)] => {
1344                match (e1.borrow().clone(),e2.borrow().clone()) {
1345                  // s m1 r2
1346                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)),Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e2))) => {
1347                    out[0] = e0.borrow().clone();
1348                    return Ok(Box::new(HorizontalConcatenateSM1R2{e0: e1.clone(), e1: e2.clone(), out: new_ref(out)}));
1349                  }
1350                  // s r2 m1
1351                  (Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e1)), Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1352                    out[0] = e0.borrow().clone();
1353                    return Ok(Box::new(HorizontalConcatenateSR2M1 { e0: e1.clone(), e1: e2.clone(), out: new_ref(out) }));
1354                  }
1355                  _ => todo!(),
1356                }
1357              }
1358              [Value::MutableReference(e0), Value::[<$kind:camel>](e1), Value::MutableReference(e2)] => {
1359                match (e0.borrow().clone(), e2.borrow().clone()) {
1360                  // m1 s r2
1361                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)), Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e2))) => {
1362                    out[1] = e1.borrow().clone();
1363                    return Ok(Box::new(HorizontalConcatenateM1SR2 { e0: e0.clone(), e1: e2.clone(), out: new_ref(out) }));
1364                  }
1365                  // r2 s m1
1366                  (Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e0)), Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1367                    out[2] = e1.borrow().clone();
1368                    return Ok(Box::new(HorizontalConcatenateR2SM1 { e0: e0.clone(), e1: e2.clone(), out: new_ref(out) }));
1369                  }
1370                  _ => todo!(),
1371                }
1372              }
1373              [Value::MutableReference(e0), Value::MutableReference(e1), Value::[<$kind:camel>](e2)] => {
1374                match (e0.borrow().clone(), e1.borrow().clone()) {
1375                  // m1 r2 s
1376                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)), Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e1))) => {
1377                    out[3] = e2.borrow().clone();
1378                    return Ok(Box::new(HorizontalConcatenateM1R2S { e0: e0.clone(), e1: e1.clone(), out: new_ref(out) }));
1379                  }
1380                  // r2 m1 s
1381                  (Value::[<Matrix $kind:camel>](Matrix::RowVector2(ref e0)), Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1))) => {
1382                    out[3] = e2.borrow().clone();
1383                    return Ok(Box::new(HorizontalConcatenateR2M1S { e0: e0.clone(), e1: e1.clone(), out: new_ref(out) }));
1384                  }
1385                  _ => todo!(),
1386                }
1387              }
1388              _ => todo!()
1389            }
1390          }
1391          #[cfg(feature = "RowVectorD")]
1392          (3,1,n) => {
1393            let mut out = RowDVector::from_element(n,$default);
1394            match &arguments[..] {
1395              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2)] => {
1396                match (e0.borrow().clone(),e1.borrow().clone(),e2.borrow().clone()) {
1397                  (Value::[<Matrix $kind:camel>](e0),Value::[<Matrix $kind:camel>](e1),Value::[<Matrix $kind:camel>](e2)) => {
1398                    let e0 = e0.get_copyable_matrix();
1399                    let e1 = e1.get_copyable_matrix();
1400                    let e2 = e2.get_copyable_matrix();
1401                    return Ok(Box::new(HorizontalConcatenateRD3{e0: e0, e1: e1, e2: e2, out: new_ref(out)}));
1402                  }
1403                  _ => todo!(),
1404                }
1405              }
1406              _ => todo!(),
1407            }
1408          }
1409          #[cfg(feature = "RowVector4")]
1410          (4,1,4) => {
1411            let mut out = RowVector4::from_element($default);
1412            match &arguments[..] {
1413             // s s s m1
1414              [Value::[<$kind:camel>](e0), Value::[<$kind:camel>](e1), Value::[<$kind:camel>](e2), Value::MutableReference(e3)] => {
1415                match (e3.borrow().clone()) {
1416                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e3))) => {
1417                    out[0] = e0.borrow().clone();
1418                    out[1] = e1.borrow().clone();
1419                    out[2] = e2.borrow().clone();
1420                    return Ok(Box::new(HorizontalConcatenateSSSM1 { e0: e3.clone(), out: new_ref(out) }));
1421                  }
1422                  _ => todo!(),
1423                }
1424              }
1425              // s s m1 s
1426              [Value::[<$kind:camel>](e0), Value::[<$kind:camel>](e1), Value::MutableReference(e2), Value::[<$kind:camel>](e3)] => {
1427                match (e2.borrow().clone()) {
1428                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1429                    out[0] = e0.borrow().clone();
1430                    out[1] = e1.borrow().clone();
1431                    out[3] = e3.borrow().clone();
1432                    return Ok(Box::new(HorizontalConcatenateSSM1S { e0: e2.clone(), out: new_ref(out) }));
1433                  }
1434                  _ => todo!(),
1435                }
1436              }
1437              
1438              // s m1 s s
1439              [Value::[<$kind:camel>](e0), Value::MutableReference(e1), Value::[<$kind:camel>](e2), Value::[<$kind:camel>](e3)] => {
1440                match (e1.borrow().clone()) {
1441                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1))) => {
1442                    out[0] = e0.borrow().clone();
1443                    out[2] = e2.borrow().clone();
1444                    out[3] = e3.borrow().clone();
1445                    return Ok(Box::new(HorizontalConcatenateSM1SS { e0: e1.clone(), out: new_ref(out) }));
1446                  }
1447                  _ => todo!(),
1448                }
1449              }
1450              // m1 s s s
1451              [Value::MutableReference(e0), Value::[<$kind:camel>](e1), Value::[<$kind:camel>](e2), Value::[<$kind:camel>](e3)] => {
1452                match (e0.borrow().clone()) {
1453                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0))) => {
1454                    out[1] = e1.borrow().clone();
1455                    out[2] = e2.borrow().clone();
1456                    out[3] = e3.borrow().clone();
1457                    return Ok(Box::new(HorizontalConcatenateM1SSS { e0: e0.clone(), out: new_ref(out) }));
1458                  }
1459                  _ => todo!(),
1460                }
1461              }
1462              
1463              // s s m1 m1
1464              [Value::[<$kind:camel>](e0), Value::[<$kind:camel>](e1), Value::MutableReference(e2), Value::MutableReference(e3)] => {
1465                match (e2.borrow().clone(), e3.borrow().clone()) {
1466                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2)), Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e3))) => {
1467                    out[0] = e0.borrow().clone();
1468                    out[1] = e1.borrow().clone();
1469                    return Ok(Box::new(HorizontalConcatenateSSM1M1 { e0: e2.clone(), e1: e3.clone(), out: new_ref(out) }));
1470                  }
1471                  _ => todo!(),
1472                }
1473              }
1474              
1475              // m1 m1 s s
1476              [Value::MutableReference(e0), Value::MutableReference(e1), Value::[<$kind:camel>](e2), Value::[<$kind:camel>](e3)] => {
1477                match (e0.borrow().clone(), e1.borrow().clone()) {
1478                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1))) => {
1479                    out[2] = e2.borrow().clone();
1480                    out[3] = e3.borrow().clone();
1481                    return Ok(Box::new(HorizontalConcatenateM1M1SS { e0: e0.clone(), e1: e1.clone(), out: new_ref(out) }));
1482                  }
1483                  _ => todo!(),
1484                }
1485              }
1486              
1487              // s m1 m1 s
1488              [Value::[<$kind:camel>](e0), Value::MutableReference(e1), Value::MutableReference(e2), Value::[<$kind:camel>](e3)] => {
1489                match (e1.borrow().clone(), e2.borrow().clone()) {
1490                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)),Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1491                    out[0] = e0.borrow().clone();
1492                    out[3] = e3.borrow().clone();
1493                    return Ok(Box::new(HorizontalConcatenateSM1M1S { e0: e1.clone(), e1: e2.clone(), out: new_ref(out) }));
1494                  }
1495                  _ => todo!(),
1496                }
1497              }
1498              
1499              // m1 s s m1
1500              [Value::MutableReference(e0), Value::[<$kind:camel>](e1), Value::[<$kind:camel>](e2), Value::MutableReference(e3)] => {
1501                match (e0.borrow().clone(), e3.borrow().clone()) {
1502                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e3))) => {
1503                    out[1] = e1.borrow().clone();
1504                    out[2] = e2.borrow().clone();
1505                    return Ok(Box::new(HorizontalConcatenateM1SSM1 { e0: e0.clone(), e1: e3.clone(), out: new_ref(out) }));
1506                  }
1507                  _ => todo!(),
1508                }
1509              }
1510              
1511              // m1 s m1 s
1512              [Value::MutableReference(e0), Value::[<$kind:camel>](e1), Value::MutableReference(e2), Value::[<$kind:camel>](e3)] => {
1513                match (e0.borrow().clone(), e2.borrow().clone()) {
1514                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1515                    out[1] = e1.borrow().clone();
1516                    out[3] = e3.borrow().clone();
1517                    return Ok(Box::new(HorizontalConcatenateM1SM1S { e0: e0.clone(), e1: e2.clone(), out: new_ref(out) }));
1518                  }
1519                  _ => todo!(),
1520                }
1521              }
1522              
1523              // s m1 s m1
1524              [Value::[<$kind:camel>](e0), Value::MutableReference(e1), Value::[<$kind:camel>](e2), Value::MutableReference(e3)] => {
1525                match (e1.borrow().clone(), e3.borrow().clone()) {
1526                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)),Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e3))) => {
1527                    out[0] = e0.borrow().clone();
1528                    out[2] = e2.borrow().clone();
1529                    return Ok(Box::new(HorizontalConcatenateSM1SM1 { e0: e1.clone(), e1: e3.clone(), out: new_ref(out) }));
1530                  }
1531                  _ => todo!(),
1532                }
1533              }
1534
1535              // s m1 m1 m1
1536              [Value::[<$kind:camel>](e0), Value::MutableReference(e1), Value::MutableReference(e2), Value::MutableReference(e3)] => {
1537                match (e1.borrow().clone(), e2.borrow().clone(), e3.borrow().clone()) {
1538                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)),Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2)),Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e3))) => {
1539                    out[0] = e0.borrow().clone();
1540                    return Ok(Box::new(HorizontalConcatenateSM1M1M1 { e0: e1.clone(), e1: e2.clone(), e2: e3.clone(), out: new_ref(out) }));
1541                  }
1542                  _ => todo!(),
1543                }
1544              }
1545
1546              // m1 s m1 m1
1547              [Value::MutableReference(e0), Value::[<$kind:camel>](e1), Value::MutableReference(e2), Value::MutableReference(e3)] => {
1548                match (e0.borrow().clone(), e2.borrow().clone(), e3.borrow().clone()) {
1549                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),
1550                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2)),
1551                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e3))) => {
1552                    out[1] = e1.borrow().clone();
1553                    return Ok(Box::new(HorizontalConcatenateM1SM1M1 { e0: e0.clone(), e1: e2.clone(), e2: e3.clone(), out: new_ref(out) }));
1554                  }
1555                  _ => todo!(),
1556                }
1557              }
1558
1559              // m1 m1 s m1
1560              [Value::MutableReference(e0), Value::MutableReference(e1), Value::[<$kind:camel>](e2), Value::MutableReference(e3)] => {
1561                match (e0.borrow().clone(), e1.borrow().clone(), e3.borrow().clone()) {
1562                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),
1563                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)),
1564                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e3))) => {
1565                    out[2] = e2.borrow().clone();
1566                    return Ok(Box::new(HorizontalConcatenateM1M1SM1 { e0: e0.clone(), e1: e1.clone(), e2: e3.clone(), out: new_ref(out) }));
1567                  }
1568                  _ => todo!(),
1569                }
1570              }
1571
1572              // m1 m1 m1 s
1573              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2), Value::[<$kind:camel>](e3)] => {
1574                match (e0.borrow().clone(), e1.borrow().clone(), e2.borrow().clone()) {
1575                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),
1576                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)),
1577                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2))) => {
1578                    out[3] = e3.borrow().clone();
1579                    return Ok(Box::new(HorizontalConcatenateM1M1M1S { e0: e0.clone(), e1: e1.clone(), e2: e2.clone(), out: new_ref(out) }));
1580                  }
1581                  _ => todo!(),
1582                }
1583              }
1584
1585              // m1 m1 m1 m1
1586              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2), Value::MutableReference(e3)] => {
1587                match (e0.borrow().clone(), e1.borrow().clone(), e2.borrow().clone(), e3.borrow().clone()) {
1588                  (Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e0)),
1589                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e1)),
1590                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e2)),
1591                   Value::[<Matrix $kind:camel>](Matrix::Matrix1(ref e3))) => {
1592                    return Ok(Box::new(HorizontalConcatenateM1M1M1M1 { e0: e0.clone(), e1: e1.clone(), e2: e2.clone(), e3: e3.clone(), out: new_ref(out) }));
1593                  }
1594                  _ => todo!(),
1595                }
1596              }
1597              _ => todo!(),
1598            }
1599          }
1600          #[cfg(feature = "RowVectorD")]
1601          (4,1,n) => {
1602            let mut out = RowDVector::from_element(n,$default);
1603            match &arguments[..] {
1604              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2), Value::MutableReference(e3)] => {
1605                match (e0.borrow().clone(), e1.borrow().clone(), e2.borrow().clone(), e3.borrow().clone()) {
1606                  (Value::[<Matrix $kind:camel>](e0),Value::[<Matrix $kind:camel>](e1),Value::[<Matrix $kind:camel>](e2),Value::[<Matrix $kind:camel>](e3)) => {
1607                    let e0 = e0.get_copyable_matrix();
1608                    let e1 = e1.get_copyable_matrix();
1609                    let e2 = e2.get_copyable_matrix();
1610                    let e3 = e3.get_copyable_matrix();
1611                    return Ok(Box::new(HorizontalConcatenateRD4{e0: e0, e1: e1, e2: e2, e3: e3, out: new_ref(out)}));
1612                  }
1613                  _ => todo!(),
1614                }
1615              }
1616              _ => todo!(),
1617            }
1618          }
1619          #[cfg(feature = "RowVectorD")]
1620          (m,1,n) => {
1621            let mut out = RowDVector::from_element(n,$default);
1622            let mut matrix_args: Vec<(Box<dyn CopyMat<$kind>>,usize)> = vec![];
1623            let mut scalar_args: Vec<(Ref<$kind>,usize)> = vec![];
1624            let mut i = 0;
1625            for arg in arguments.iter() {
1626              match &arg {
1627                Value::[<$kind:camel>](e0) => {
1628                  scalar_args.push((e0.clone(),i));
1629                  i += 1;
1630                }
1631                Value::MutableReference(e0) => {
1632                  match e0.borrow().clone() {
1633                    Value::[<Matrix $kind:camel>](e0) => {
1634                      matrix_args.push((e0.get_copyable_matrix(),i));
1635                      i += e0.shape()[1];
1636                    }
1637                    Value::[<$kind:camel>](e0) => {
1638                      scalar_args.push((e0.clone(),i));
1639                      i += 1;
1640                    }
1641                    _ => todo!(),
1642                  }
1643                }
1644                _ => todo!(),
1645              }
1646            }
1647            return Ok(Box::new(HorizontalConcatenateRDN{scalar: scalar_args, matrix: matrix_args, out: new_ref(out)}));
1648          }
1649          #[cfg(feature = "Vector2")]
1650          (1,2,1) => {
1651            // v2
1652            match &arguments[..] {
1653              [Value::MutableReference(e0)] => {
1654                match *e0.borrow() {
1655                  Value::[<Matrix $kind:camel>](Matrix::Vector2(ref e0)) => {return Ok(Box::new(HorizontalConcatenateV2{out: e0.clone()}));}
1656                  _ => todo!(),
1657                }
1658              }
1659              _ => todo!(),
1660            }
1661          }
1662          #[cfg(feature = "Matrix2")]
1663          (1,2,2) => {
1664            // m2
1665            match &arguments[..] {
1666              [Value::MutableReference(e0)] => {
1667                match *e0.borrow() {
1668                  Value::[<Matrix $kind:camel>](Matrix::Matrix2(ref e0)) => {return Ok(Box::new(HorizontalConcatenateM2{out: e0.clone()}));}
1669                  _ => todo!(),
1670                }
1671              }
1672              _ => todo!(),
1673            }
1674          }
1675          #[cfg(feature = "Matrix2x3")]
1676          (1,2,3) => {
1677            // m2x3
1678            match &arguments[..] {
1679              [Value::MutableReference(e0)] => {
1680                match *e0.borrow() {
1681                  Value::[<Matrix $kind:camel>](Matrix::Matrix2x3(ref e0)) => {return Ok(Box::new(HorizontalConcatenateM2x3{out: e0.clone()}));}
1682                  _ => todo!(),
1683                }
1684              }
1685              _ => todo!(),
1686            }
1687          }
1688          #[cfg(feature = "Vector3")]
1689          (1,3,1) => {
1690            // v3
1691            match &arguments[..] {
1692              [Value::MutableReference(e0)] => {
1693                match *e0.borrow() {
1694                  Value::[<Matrix $kind:camel>](Matrix::Vector3(ref e0)) => {return Ok(Box::new(HorizontalConcatenateV3{out: e0.clone()}));}
1695                  _ => todo!(),
1696                }
1697              }
1698              _ => todo!(),
1699            }
1700          }
1701          #[cfg(feature = "Matrix3x2")]
1702          (1,3,2) => {
1703            // m3x2
1704            match &arguments[..] {
1705              [Value::MutableReference(e0)] => {
1706                match *e0.borrow() {
1707                  Value::[<Matrix $kind:camel>](Matrix::Matrix3x2(ref e0)) => {return Ok(Box::new(HorizontalConcatenateM3x2{out: e0.clone()}));}
1708                  _ => todo!(),
1709                }
1710              }
1711              _ => todo!(),
1712            }
1713          }
1714          #[cfg(feature = "Matrix3")]
1715          (1,3,3) => {
1716            // m3
1717            match &arguments[..] {
1718              [Value::MutableReference(e0)] => {
1719                match *e0.borrow() {
1720                  Value::[<Matrix $kind:camel>](Matrix::Matrix3(ref e0)) => {return Ok(Box::new(HorizontalConcatenateM3{out: e0.clone()}));}
1721                  _ => todo!(),
1722                }
1723              }
1724              _ => todo!(),
1725            }
1726          }
1727          #[cfg(feature = "Vector4")]
1728          (1,4,1) => {
1729            // v4
1730            match &arguments[..] {
1731              [Value::MutableReference(e0)] => {
1732                match *e0.borrow() {
1733                  Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e0)) => {return Ok(Box::new(HorizontalConcatenateV4{out: e0.clone()}));}
1734                  _ => todo!(),
1735                }
1736              }
1737              _ => todo!(),
1738            }
1739          }
1740          #[cfg(feature = "Matrix4")]
1741          (1,4,4) => {
1742            // m4
1743            match &arguments[..] {
1744              [Value::MutableReference(e0)] => {
1745                match *e0.borrow() {
1746                  Value::[<Matrix $kind:camel>](Matrix::Matrix4(ref e0)) => {return Ok(Box::new(HorizontalConcatenateM4{out: e0.clone()}));}
1747                  _ => todo!(),
1748                }
1749              }
1750              _ => todo!(),
1751            }
1752          }
1753          #[cfg(feature = "MatrixD")]
1754          (1,m,n) => {
1755            // md
1756            match &arguments[..] {
1757              [Value::MutableReference(e0)] => {
1758                match *e0.borrow() {
1759                  Value::[<Matrix $kind:camel>](Matrix::DMatrix(ref e0)) => {return Ok(Box::new(HorizontalConcatenateMD{out: e0.clone()}));}
1760                  _ => todo!(),
1761                }
1762              }
1763              _ => todo!(),
1764            }
1765          }
1766          #[cfg(feature = "Matrix2")]
1767          (2,2,2) => {
1768            let mut out = Matrix2::from_element($default);
1769            match &arguments[..] {
1770              [Value::MutableReference(e0), Value::MutableReference(e1)] => {
1771                match (e0.borrow().clone(), e1.borrow().clone()) {
1772                  // v2v2
1773                  (Value::[<Matrix $kind:camel>](Matrix::Vector2(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Vector2(ref e1))) => {return Ok(Box::new(HorizontalConcatenateV2V2{e0: e0.clone(), e1: e1.clone(), out: new_ref(out)}));}
1774                  _ => todo!(),
1775                }
1776              }  
1777              _ => todo!(),
1778            }
1779          }
1780          #[cfg(feature = "Matrix3x2")]
1781          (2,3,2) => {
1782            let mut out = Matrix3x2::from_element($default);
1783            match &arguments[..] {
1784              [Value::MutableReference(e0), Value::MutableReference(e1)] => {
1785                match (e0.borrow().clone(), e1.borrow().clone()) {
1786                  // v3v3
1787                  (Value::[<Matrix $kind:camel>](Matrix::Vector3(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Vector3(ref e1))) => {return Ok(Box::new(HorizontalConcatenateV3V3{e0: e0.clone(), e1: e1.clone(), out: new_ref(out)}));}
1788                  _ => todo!(),
1789                }
1790              }  
1791              _ => todo!(),
1792            }
1793          }
1794          #[cfg(feature = "Matrix2x3")]
1795          (2,2,3) => {
1796            let mut out = Matrix2x3::from_element($default);
1797            match &arguments[..] {
1798              [Value::MutableReference(e0), Value::MutableReference(e1)] => {
1799                match (e0.borrow().clone(), e1.borrow().clone()) {
1800                  // v2m2
1801                  (Value::[<Matrix $kind:camel>](Matrix::Vector2(ref e0)), Value::[<Matrix $kind:camel>](Matrix::Matrix2(ref e1))) => {return Ok(Box::new(HorizontalConcatenateV2M2{e0: e0.clone(), e1: e1.clone(), out: new_ref(out)}));}
1802                  // m2v2
1803                  (Value::[<Matrix $kind:camel>](Matrix::Matrix2(ref e0)), Value::[<Matrix $kind:camel>](Matrix::Vector2(ref e1))) => {return Ok(Box::new(HorizontalConcatenateM2V2{e0: e0.clone(),e1: e1.clone(),out: new_ref(out),}));}
1804                  _ => todo!(),
1805                }
1806              }
1807              _ => todo!(),
1808            }
1809          }
1810          #[cfg(feature = "Matrix3")]
1811          (2,3,3) => {
1812            let mut out = Matrix3::from_element($default);
1813            match &arguments[..] {
1814              [Value::MutableReference(e0), Value::MutableReference(e1)] => {
1815                match (e0.borrow().clone(), e1.borrow().clone()) {
1816                  // v3m3x2
1817                  (Value::[<Matrix $kind:camel>](Matrix::Vector3(ref e0)), Value::[<Matrix $kind:camel>](Matrix::Matrix3x2(ref e1))) => {return Ok(Box::new(HorizontalConcatenateV3M3x2 { e0: e0.clone(), e1: e1.clone(), out: new_ref(out) }));}
1818                  // m3x2v3
1819                  (Value::[<Matrix $kind:camel>](Matrix::Matrix3x2(ref e0)), Value::[<Matrix $kind:camel>](Matrix::Vector3(ref e1))) => {return Ok(Box::new(HorizontalConcatenateM3x2V3 { e0: e0.clone(), e1: e1.clone(), out: new_ref(out) }));}
1820                  _ => todo!(),
1821                }
1822              }
1823              _ => todo!(),
1824            }
1825          }
1826          #[cfg(feature = "Matrix4")]
1827          (2,4,4) => {
1828            let mut out = Matrix4::from_element($default);
1829            match &arguments[..] {
1830              [Value::MutableReference(e0), Value::MutableReference(e1)] => {
1831                match (e0.borrow().clone(), e1.borrow().clone()) {
1832                  // v4md
1833                  (Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e0)),Value::[<Matrix $kind:camel>](Matrix::DMatrix(ref e1)))=>Ok(Box::new(HorizontalConcatenateV4MD{e0:e0.clone(),e1:e1.clone(),out:new_ref(out)})),
1834                  // mdv4
1835                  (Value::[<Matrix $kind:camel>](Matrix::DMatrix(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e1)))=>Ok(Box::new(HorizontalConcatenateMDV4{e0:e0.clone(),e1:e1.clone(),out:new_ref(out)})),
1836                  // mdmd
1837                  (Value::[<Matrix $kind:camel>](Matrix::DMatrix(ref e0)),Value::[<Matrix $kind:camel>](Matrix::DMatrix(ref e1)))=>Ok(Box::new(HorizontalConcatenateMDMD{e0:e0.clone(),e1:e1.clone(),out:new_ref(out)})),
1838                  _ => todo!(),
1839                }
1840              }
1841              _ => todo!(),
1842            }
1843          }
1844          #[cfg(feature = "MatrixD")]
1845          (2,m,n) => {
1846            let mut out = DMatrix::from_element(m,n,$default);
1847            match &arguments[..] {
1848              [Value::MutableReference(e0), Value::MutableReference(e1)] => {
1849                match (e0.borrow().clone(), e1.borrow().clone()) {
1850                  (Value::[<Matrix $kind:camel>](m0),Value::[<Matrix $kind:camel>](m1)) => {
1851                    let e0 = m0.get_copyable_matrix();
1852                    let e1 = m1.get_copyable_matrix();
1853                    Ok(Box::new(HorizontalConcatenateTwoArgs{e0,e1,out:new_ref(out)}))
1854                  }   
1855                  _ => todo!(),
1856                }
1857              }
1858              _ => todo!(),
1859            }
1860          }
1861          #[cfg(feature = "Matrix2x3")]
1862          (3, 2, 3) => {
1863            let mut out = Matrix2x3::from_element($default);
1864            match &arguments[..] {
1865              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2)] => {
1866                match (e0.borrow().clone(), e1.borrow().clone(),e2.borrow().clone()) {
1867                  // v2v2v2
1868                  (Value::[<Matrix $kind:camel>](Matrix::Vector2(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Vector2(ref e1)),Value::[<Matrix $kind:camel>](Matrix::Vector2(ref e2)))=>Ok(Box::new(HorizontalConcatenateV2V2V2{e0:e0.clone(),e1:e1.clone(),e2:e2.clone(),out:new_ref(out)})),
1869                  _ => todo!(),
1870                }
1871              }
1872              _ => todo!(),
1873            }
1874          }
1875          #[cfg(feature = "Matrix3")]
1876          (3, 3, 3) => {
1877            let mut out = Matrix3::from_element($default);
1878            match &arguments[..] {
1879              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2)] => {
1880                match (e0.borrow().clone(), e1.borrow().clone(),e2.borrow().clone()) {
1881                  // v3v3v3
1882                  (Value::[<Matrix $kind:camel>](Matrix::Vector3(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Vector3(ref e1)),Value::[<Matrix $kind:camel>](Matrix::Vector3(ref e2)))=>Ok(Box::new(HorizontalConcatenateV3V3V3{e0:e0.clone(),e1:e1.clone(),e2:e2.clone(),out:new_ref(out)})),
1883                  _ => todo!(),
1884                }
1885              }
1886              _ => todo!(),
1887            }
1888          }
1889          #[cfg(feature = "Matrix4")]
1890          (3, 4, 4) => {
1891            let mut out = Matrix4::from_element($default);
1892            match &arguments[..] {
1893              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2)] => {
1894                match (e0.borrow().clone(), e1.borrow().clone(),e2.borrow().clone()) {
1895                  // v4v4md
1896                  (Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e1)),Value::[<Matrix $kind:camel>](Matrix::DMatrix(ref e2)))=>Ok(Box::new(HorizontalConcatenateV4V4MD{e0:e0.clone(),e1:e1.clone(),e2:e2.clone(),out:new_ref(out)})),
1897                  // v4mdv4
1898                  (Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e0)),Value::[<Matrix $kind:camel>](Matrix::DMatrix(ref e1)),Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e2)))=>Ok(Box::new(HorizontalConcatenateV4MDV4{e0:e0.clone(),e1:e1.clone(),e2:e2.clone(),out:new_ref(out)})),
1899                  // mdv4v4
1900                  (Value::[<Matrix $kind:camel>](Matrix::DMatrix(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e1)),Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e2)))=>Ok(Box::new(HorizontalConcatenateMDV4V4{e0:e0.clone(),e1:e1.clone(),e2:e2.clone(),out:new_ref(out)})),
1901                  _ => todo!(),
1902                }
1903              }
1904              _ => todo!(),
1905            }
1906          }
1907          #[cfg(feature = "MatrixD")]
1908          (3, m, n) => {
1909            let mut out = DMatrix::from_element(m,n,$default);
1910            match &arguments[..] {
1911              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2)] => {
1912                match (e0.borrow().clone(), e1.borrow().clone(),e2.borrow().clone()) {
1913                  (Value::[<Matrix $kind:camel>](m0),Value::[<Matrix $kind:camel>](m1),Value::[<Matrix $kind:camel>](m2)) => {
1914                    let e0 = m0.get_copyable_matrix();
1915                    let e1 = m1.get_copyable_matrix();
1916                    let e2 = m2.get_copyable_matrix();
1917                    Ok(Box::new(HorizontalConcatenateThreeArgs{e0,e1,e2,out:new_ref(out)}))
1918                  }   
1919                  _ => todo!(),
1920                }
1921              }
1922              _ => todo!(),
1923            }
1924          }
1925          #[cfg(feature = "Matrix4")]
1926          (4, 4, 4) => {
1927            let mut out = Matrix4::from_element($default);
1928            match &arguments[..] {
1929              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2), Value::MutableReference(e3)] => {
1930                match (e0.borrow().clone(), e1.borrow().clone(),e2.borrow().clone(), e3.borrow().clone()) {
1931                  // v4v4v4v4
1932                  (Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e0)),Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e1)),Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e2)),Value::[<Matrix $kind:camel>](Matrix::Vector4(ref e3)))=>Ok(Box::new(HorizontalConcatenateV4V4V4V4{e0:e0.clone(),e1:e1.clone(),e2:e2.clone(),e3:e3.clone(),out:new_ref(out)})),
1933                  _ => todo!(),
1934                }
1935              }
1936              _ => todo!(),
1937            }
1938          }
1939          #[cfg(feature = "MatrixD")]
1940          (4, m, n) => {
1941            let mut out = DMatrix::from_element(m,n,$default);
1942            match &arguments[..] {
1943              [Value::MutableReference(e0), Value::MutableReference(e1), Value::MutableReference(e2), Value::MutableReference(e3)] => {
1944                match (e0.borrow().clone(), e1.borrow().clone(),e2.borrow().clone(),e3.borrow().clone()) {
1945                  (Value::[<Matrix $kind:camel>](m0),Value::[<Matrix $kind:camel>](m1),Value::[<Matrix $kind:camel>](m2),Value::[<Matrix $kind:camel>](m3)) => {
1946                    let e0 = m0.get_copyable_matrix();
1947                    let e1 = m1.get_copyable_matrix();
1948                    let e2 = m2.get_copyable_matrix();
1949                    let e3 = m3.get_copyable_matrix();
1950                    Ok(Box::new(HorizontalConcatenateFourArgs{e0,e1,e2,e3,out:new_ref(out)}))
1951                  }   
1952                  _ => todo!(),
1953                }
1954              }
1955              _ => todo!(),
1956            }
1957          }
1958          #[cfg(feature = "MatrixD")]
1959          (l, m, n) => {
1960            let mut out = DMatrix::from_element(m,n,$default);
1961            let mut args = vec![];
1962            for arg in arguments {
1963              match arg {
1964                Value::MutableReference(e0) => {
1965                  match e0.borrow().clone() {
1966                    Value::[<Matrix $kind:camel>](m0) => {
1967                      let e0 = m0.get_copyable_matrix();
1968                      args.push(e0);
1969                    }
1970                    _ => todo!(),
1971                  }
1972                }
1973                _ => todo!(),
1974              }
1975            }
1976            Ok(Box::new(HorizontalConcatenateNArgs{e0: args, out:new_ref(out)}))
1977          }
1978          _ => {return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind});}
1979        }
1980  }}}}}
1981
1982fn impl_horzcat_fxn(arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
1983  // are they all the same?
1984  //let same = kinds.iter().all(|x| *x == target_kind);
1985  let kinds: Vec<ValueKind> = arguments.iter().map(|x| x.kind()).collect::<Vec<ValueKind>>();
1986  let target_kind = kinds[0].clone();
1987  if ValueKind::is_compatible(target_kind.clone(), ValueKind::F64)  { impl_horzcat_arms!(F64,arguments,F64::zero())
1988  } else if ValueKind::is_compatible(target_kind.clone(), ValueKind::F32)  { impl_horzcat_arms!(F32,arguments,F32::zero())
1989  } else if ValueKind::is_compatible(target_kind.clone(), ValueKind::U8)  { impl_horzcat_arms!(u8,arguments,u8::zero())    
1990  } else if ValueKind::is_compatible(target_kind.clone(), ValueKind::U16)  { impl_horzcat_arms!(u16,arguments,u16::zero())    
1991  } else if ValueKind::is_compatible(target_kind.clone(), ValueKind::U32)  { impl_horzcat_arms!(u32,arguments,u32::zero())    
1992  } else if ValueKind::is_compatible(target_kind.clone(), ValueKind::U64)  { impl_horzcat_arms!(u64,arguments,u64::zero())    
1993  } else if ValueKind::is_compatible(target_kind.clone(), ValueKind::U128)  { impl_horzcat_arms!(u128,arguments,u128::zero())    
1994  } else if ValueKind::is_compatible(target_kind.clone(), ValueKind::Bool)  { impl_horzcat_arms!(bool,arguments,false)
1995  } else {
1996    todo!();
1997  }
1998}
1999
2000pub struct MaxtrixHorzCat {}
2001impl NativeFunctionCompiler for MaxtrixHorzCat {
2002  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
2003    // First, get the size of the output matrix
2004    // rows are consistent already so we can just get nrows from the first element
2005    impl_horzcat_fxn(arguments)
2006  }
2007}