Skip to main content

mech_interpreter/stdlib/convert/
mat_to_mat.rs

1#[macro_use]
2use crate::stdlib::*;
3
4use nalgebra::{Scalar, Matrix3, Matrix4, DVector, ArrayStorage, Const};
5use std::fmt::Debug;
6use std::ops::{Index, IndexMut};
7use std::marker::PhantomData;
8
9#[derive(Debug)]
10pub struct ConvertMatToMat2<TFrom, TTo, FromMat, ToMat> {
11    pub arg: Ref<FromMat>,
12    pub out: Ref<ToMat>,
13    _marker: PhantomData<(TFrom, TTo)>, 
14}
15
16impl<TFrom, TTo, FromMat, ToMat> MechFunctionImpl for ConvertMatToMat2<TFrom, TTo, FromMat, ToMat>
17where
18    Ref<ToMat>: ToValue,
19    TFrom: LosslessInto<TTo> + Debug + Scalar + Clone,
20    TTo: Debug + Scalar,
21    for<'a> &'a FromMat: IntoIterator<Item = &'a TFrom>,
22    for<'a> &'a mut ToMat: IntoIterator<Item = &'a mut TTo>,
23    FromMat: Debug,
24    ToMat: Debug,
25  {
26    fn solve(&self) {
27      let arg_ptr = self.arg.as_ptr();
28      let out_ptr = self.out.as_mut_ptr();
29      unsafe {
30        let arg_ref: &FromMat = &*arg_ptr;
31        let out_ref: &mut ToMat = &mut *out_ptr;
32        for (dst, src) in (&mut *out_ref).into_iter().zip((&*arg_ref).into_iter()) {
33          *dst = src.clone().lossless_into();
34        }
35      }
36    }
37    fn out(&self) -> Value {self.out.to_value()}
38    fn to_string(&self) -> String { format!("{:#?}",self) }
39  }
40#[cfg(feature = "compiler")]
41impl<TFrom, TTo, FromMat, ToMat> MechFunctionCompiler for ConvertMatToMat2<TFrom, TTo, FromMat, ToMat> 
42where
43  TFrom: ConstElem + CompileConst + AsValueKind,
44  TTo: ConstElem + CompileConst + AsValueKind,
45  FromMat: CompileConst + ConstElem + AsValueKind,
46  ToMat: CompileConst + ConstElem + AsValueKind,
47{
48  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
49    let name = format!("ConvertMatToMat2<{},{}>", FromMat::as_value_kind(), ToMat::as_value_kind());
50    compile_unop!(name, self.out, self.arg, ctx, FeatureFlag::Builtin(FeatureKind::Convert));
51  }
52}
53
54fn create_convert_mat_to_mat<TFrom, TTo>(
55  v: Matrix<TFrom>,
56  shape: &[usize],
57) -> MResult<Box<dyn MechFunction>>
58where
59  #[cfg(feature = "matrix1")]
60  Ref<na::Matrix1<TTo>>: ToValue,
61  #[cfg(feature = "matrix2")]
62  Ref<na::Matrix2<TTo>>: ToValue,
63  #[cfg(feature = "matrix3")]
64  Ref<na::Matrix3<TTo>>: ToValue,
65  #[cfg(feature = "matrix4")]
66  Ref<na::Matrix4<TTo>>: ToValue,
67  #[cfg(feature = "matrix3x2")]
68  Ref<na::Matrix3x2<TTo>>: ToValue,
69  #[cfg(feature = "matrix2x3")]
70  Ref<na::Matrix2x3<TTo>>: ToValue,
71  #[cfg(feature = "row_vector2")]
72  Ref<na::RowVector2<TTo>>: ToValue,
73  #[cfg(feature = "row_vector3")]
74  Ref<na::RowVector3<TTo>>: ToValue,
75  #[cfg(feature = "row_vector4")]
76  Ref<na::RowVector4<TTo>>: ToValue,
77  #[cfg(feature = "vector2")]
78  Ref<na::Vector2<TTo>>: ToValue,
79  #[cfg(feature = "vector3")]
80  Ref<na::Vector3<TTo>>: ToValue,
81  #[cfg(feature = "vector4")]
82  Ref<na::Vector4<TTo>>: ToValue,
83  #[cfg(feature = "vectord")]
84  Ref<na::DVector<TTo>>: ToValue,
85  #[cfg(feature = "row_vectord")]
86  Ref<na::RowDVector<TTo>>: ToValue,
87  #[cfg(feature = "matrixd")]
88  Ref<na::DMatrix<TTo>>: ToValue,
89  TFrom: LosslessInto<TTo> + Debug + Scalar + Clone + ConstElem + CompileConst + AsValueKind,
90  TTo: Debug + Scalar + Default + ConstElem + CompileConst + AsValueKind,
91{
92  let zero = TTo::default();
93  match v {
94    #[cfg(feature = "matrix1")]
95    Matrix::Matrix1(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix1::from_element(zero)), _marker: PhantomData })),
96    #[cfg(feature = "matrix2")]
97    Matrix::Matrix2(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix2::from_element(zero)), _marker: PhantomData })),
98    #[cfg(feature = "matrix3")]
99    Matrix::Matrix3(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix3::from_element(zero)), _marker: PhantomData })),
100    #[cfg(feature = "matrix4")]
101    Matrix::Matrix4(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix4::from_element(zero)), _marker: PhantomData })),
102    #[cfg(feature = "matrix3x2")]
103    Matrix::Matrix3x2(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix3x2::from_element(zero)), _marker: PhantomData })),
104    #[cfg(feature = "matrix2x3")]
105    Matrix::Matrix2x3(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix2x3::from_element(zero)), _marker: PhantomData })),
106    #[cfg(feature = "row_vector2")]
107    Matrix::RowVector2(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowVector2::from_element(zero)), _marker: PhantomData })),
108    #[cfg(feature = "row_vector3")]
109    Matrix::RowVector3(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowVector3::from_element(zero)), _marker: PhantomData })),
110    #[cfg(feature = "row_vector4")]
111    Matrix::RowVector4(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowVector4::from_element(zero)), _marker: PhantomData })),
112    #[cfg(feature = "vector2")]
113    Matrix::Vector2(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Vector2::from_element(zero)), _marker: PhantomData })),
114    #[cfg(feature = "vector3")]
115    Matrix::Vector3(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Vector3::from_element(zero)), _marker: PhantomData })),
116    #[cfg(feature = "vector4")]
117    Matrix::Vector4(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Vector4::from_element(zero)), _marker: PhantomData })),
118    #[cfg(feature = "vectord")]
119    Matrix::DVector(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(DVector::from_element(shape[0], zero)), _marker: PhantomData })),
120    #[cfg(feature = "row_vectord")]
121    Matrix::RowDVector(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowDVector::from_element(shape[1], zero)), _marker: PhantomData })),
122    #[cfg(feature = "matrixd")]
123    Matrix::DMatrix(v) => Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(DMatrix::from_element(shape[0], shape[1], zero)), _marker: PhantomData })),
124    _ => Err(MechError::new(
125        FeatureNotEnabledError,
126        None
127      ).with_compiler_loc()
128    ),
129  }
130}
131
132fn create_reshape_mat_to_mat<TFrom, TTo>(
133  v: Matrix<TFrom>,
134  shape: &[usize],
135) -> MResult<Box<dyn MechFunction>>
136where
137  #[cfg(feature = "matrix1")]
138  Ref<na::Matrix1<TTo>>: ToValue,
139  #[cfg(feature = "matrix2")]
140  Ref<na::Matrix2<TTo>>: ToValue,
141  #[cfg(feature = "matrix3")]
142  Ref<na::Matrix3<TTo>>: ToValue,
143  #[cfg(feature = "matrix4")]
144  Ref<na::Matrix4<TTo>>: ToValue,
145  #[cfg(feature = "matrix3x2")]
146  Ref<na::Matrix3x2<TTo>>: ToValue,
147  #[cfg(feature = "matrix2x3")]
148  Ref<na::Matrix2x3<TTo>>: ToValue,
149  #[cfg(feature = "row_vector2")]
150  Ref<na::RowVector2<TTo>>: ToValue,
151  #[cfg(feature = "row_vector3")]
152  Ref<na::RowVector3<TTo>>: ToValue,
153  #[cfg(feature = "row_vector4")]
154  Ref<na::RowVector4<TTo>>: ToValue,
155  #[cfg(feature = "vector2")]
156  Ref<na::Vector2<TTo>>: ToValue,
157  #[cfg(feature = "vector3")]
158  Ref<na::Vector3<TTo>>: ToValue,
159  #[cfg(feature = "vector4")]
160  Ref<na::Vector4<TTo>>: ToValue,
161  #[cfg(feature = "vectord")]
162  Ref<na::DVector<TTo>>: ToValue,
163  #[cfg(feature = "row_vectord")]
164  Ref<na::RowDVector<TTo>>: ToValue,
165  #[cfg(feature = "matrixd")]
166  Ref<na::DMatrix<TTo>>: ToValue,
167  TFrom: LosslessInto<TTo> + Debug + Scalar + Clone + ConstElem + CompileConst + AsValueKind,
168  TTo: Debug + Scalar + Default + ConstElem + CompileConst + AsValueKind,
169{
170  let zero = TTo::default();
171  let dims = v.shape();
172  match (v,shape[0],shape[1]) {
173    #[cfg(all(feature = "matrix2", feature = "row_vector4"))]
174    (Matrix::Matrix2(v), 1, 4) => {return Ok(Box::new(ConvertMatToMat2 {arg: v,out: Ref::new(RowVector4::from_element(zero)), _marker: PhantomData}));},
175    #[cfg(all(feature = "matrix2", feature = "vector4"))]
176    (Matrix::Matrix2(v), 4, 1) => {return Ok(Box::new(ConvertMatToMat2 {arg: v,out: Ref::new(Vector4::from_element(zero)), _marker: PhantomData}));},
177
178    #[cfg(all(feature = "matrix3", feature = "row_vectord"))]
179    (Matrix::Matrix3(v), 1, 9) => {return Ok(Box::new(ConvertMatToMat2 {arg: v,out: Ref::new(RowDVector::from_element(9, zero)), _marker: PhantomData}));},
180    #[cfg(all(feature = "matrix3", feature = "vectord"))]
181    (Matrix::Matrix3(v), 9, 1) => {return Ok(Box::new(ConvertMatToMat2 {arg: v,out: Ref::new(DVector::from_element(9, zero)), _marker: PhantomData}));},
182
183    #[cfg(all(feature = "matrix4", feature = "row_vectord"))]
184    (Matrix::Matrix4(v), 1, 16) => {return Ok(Box::new(ConvertMatToMat2 {arg: v,out: Ref::new(RowDVector::from_element(16, zero)), _marker: PhantomData}));},
185    #[cfg(all(feature = "matrix4", feature = "vectord"))]
186    (Matrix::Matrix4(v), 16, 1) => {return Ok(Box::new(ConvertMatToMat2 {arg: v,out: Ref::new(DVector::from_element(16, zero)), _marker: PhantomData}));},
187    
188    #[cfg(all(feature = "matrix3x2", feature = "row_vectord"))]
189    (Matrix::Matrix3x2(v), 1, 6) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowDVector::from_element(6, zero)), _marker: PhantomData })); },
190    #[cfg(all(feature = "matrix3x2", feature = "vectord"))]
191    (Matrix::Matrix3x2(v), 6, 1) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(DVector::from_element(6, zero)), _marker: PhantomData })); },
192    #[cfg(all(feature = "matrix3x2", feature = "matrix2x3"))]
193    (Matrix::Matrix3x2(v), 2, 3) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix2x3::from_element(zero)), _marker: PhantomData })); },
194
195    #[cfg(all(feature = "matrix2x3", feature = "row_vectord"))]
196    (Matrix::Matrix2x3(v), 1, 6) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowDVector::from_element(6, zero)), _marker: PhantomData })); },
197    #[cfg(all(feature = "matrix2x3", feature = "vectord"))]
198    (Matrix::Matrix2x3(v), 6, 1) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(DVector::from_element(6, zero)), _marker: PhantomData })); },
199    #[cfg(all(feature = "matrix2x3", feature = "matrix3x2"))]
200    (Matrix::Matrix2x3(v), 3, 2) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix3x2::from_element(zero)), _marker: PhantomData })); },
201
202    #[cfg(all(feature = "vector2", feature = "row_vector2"))]
203    (Matrix::Vector2(v), 1, 2) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowVector2::from_element(zero)), _marker: PhantomData })); },
204    #[cfg(all(feature = "vector3", feature = "row_vector3"))]
205    (Matrix::Vector3(v), 1, 3) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowVector3::from_element(zero)), _marker: PhantomData })); },
206    
207    #[cfg(all(feature = "vector4", feature = "row_vector4"))]
208    (Matrix::Vector4(v), 1, 4) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowVector4::from_element(zero)), _marker: PhantomData })); },
209    #[cfg(all(feature = "vector4", feature = "matrix2"))]
210    (Matrix::Vector4(v), 2, 2) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix2::from_element(zero)), _marker: PhantomData })); },
211
212    #[cfg(all(feature = "row_vector2", feature = "vector2"))]
213    (Matrix::RowVector2(v), 2, 1) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Vector2::from_element(zero)), _marker: PhantomData })); },
214    #[cfg(all(feature = "row_vector3", feature = "vector3"))]
215    (Matrix::RowVector3(v), 3, 1) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Vector3::from_element(zero)), _marker: PhantomData })); },
216    
217    #[cfg(all(feature = "row_vector4", feature = "vector4"))]
218    (Matrix::RowVector4(v), 4, 1) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Vector4::from_element(zero)), _marker: PhantomData })); },
219    #[cfg(all(feature = "row_vector4", feature = "matrix2"))]
220    (Matrix::RowVector4(v), 2, 2) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix2::from_element(zero)), _marker: PhantomData })); },
221    
222    #[cfg(all(feature = "row_vectord", feature = "matrix3"))]
223    (Matrix::RowDVector(v), 3, 3) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix3::from_element(zero)), _marker: PhantomData })); },
224    #[cfg(all(feature = "row_vectord", feature = "matrix4"))]
225    (Matrix::RowDVector(v), 4, 4) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix4::from_element(zero)), _marker: PhantomData })); },
226    #[cfg(all(feature = "row_vectord", feature = "matrix2x3"))]
227    (Matrix::RowDVector(v), 2, 3) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix2x3::from_element(zero)), _marker: PhantomData })); },
228    #[cfg(all(feature = "row_vectord", feature = "matrix3x2"))]
229    (Matrix::RowDVector(v), 3, 2) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix3x2::from_element(zero)), _marker: PhantomData })); },
230    #[cfg(all(feature = "row_vectord", feature = "vectord"))]
231    (Matrix::RowDVector(v), n, 1) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(DVector::from_element(n, zero)), _marker: PhantomData })); },
232    #[cfg(all(feature = "row_vectord", feature = "matrixd"))]
233    (Matrix::RowDVector(v), n, m) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(DMatrix::from_element(n, m, zero)), _marker: PhantomData })); },
234    
235    #[cfg(all(feature = "vectord", feature = "matrix3"))]
236    (Matrix::DVector(v), 3, 3) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix3::from_element(zero)), _marker: PhantomData })); },
237    #[cfg(all(feature = "vectord", feature = "matrix4"))]
238    (Matrix::DVector(v), 4, 4) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix4::from_element(zero)), _marker: PhantomData })); },
239    #[cfg(all(feature = "vectord", feature = "matrix3x2"))]
240    (Matrix::DVector(v), 3, 2) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix3x2::from_element(zero)), _marker: PhantomData })); },
241    #[cfg(all(feature = "vectord", feature = "matrix2x3"))]
242    (Matrix::DVector(v), 2, 3) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(Matrix2x3::from_element(zero)), _marker: PhantomData })); },
243    #[cfg(all(feature = "vectord", feature = "row_vectord"))]
244    (Matrix::DVector(v), 1, n) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowDVector::from_element(n, zero)), _marker: PhantomData })); },
245    #[cfg(all(feature = "vectord", feature = "matrixd"))]
246    (Matrix::DVector(v), n, m) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(DMatrix::from_element(n, m, zero)), _marker: PhantomData })); },
247    
248    #[cfg(all(feature = "matrixd", feature = "vectord"))]
249    (Matrix::DMatrix(v), n, 1) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(DVector::from_element(n, zero)), _marker: PhantomData })); },
250    #[cfg(all(feature = "matrixd", feature = "row_vectord"))]
251    (Matrix::DMatrix(v), 1, n) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(RowDVector::from_element(n, zero)), _marker: PhantomData })); },
252    #[cfg(feature = "matrixd")]
253    (Matrix::DMatrix(v), n, m) => { return Ok(Box::new(ConvertMatToMat2 { arg: v, out: Ref::new(DMatrix::from_element(n, m, zero)), _marker: PhantomData })); },
254    _ => {
255      return Err(MechError::new(
256        ReshapeError { original: (dims[0], dims[1]), requested: (shape[0], shape[1]) },
257        None
258      ).with_compiler_loc());
259    }
260  }
261}
262
263macro_rules! impl_conversion_mat_to_mat_fxn {
264  (
265    $(
266      $src:tt, $src_string:tt => [ $( $dst:tt, $dst_string:tt ),+ $(,)? ]
267    );+ $(;)?
268  ) => {
269    pub fn impl_conversion_mat_to_mat_fxn(
270      source_value: Value,
271      target_kind: ValueKind
272    ) -> MResult<Box<dyn MechFunction>> {
273      let shape = source_value.shape();
274
275      paste::paste! {
276        match (source_value.clone(), target_kind.clone()) {
277          $(
278            #[cfg(all(feature = "matrix", feature = $src_string))]
279            (Value::[<Matrix $src:camel>](v), ValueKind::Matrix(target_kind, dims)) if matches!(target_kind.as_ref(), ValueKind::Any) => {
280              if dims.is_empty() {
281                create_convert_mat_to_mat::<$src, $src>(v, &shape)
282              } else if ((shape[0] == dims[0]) && (shape[1] == dims[1])) {
283                create_convert_mat_to_mat::<$src, $src>(v, &dims)
284              } else if shape[0] * shape[1] == dims[0] * dims[1] {
285                create_reshape_mat_to_mat::<$src, $src>(v, &dims)
286              } else {
287                Err(MechError::new(UnsupportedConversionError{from: source_value.kind(), to: target_kind.as_ref().clone()}, None).with_compiler_loc())
288              }
289            }
290            $(
291              #[cfg(all(feature = "matrix", feature = $src_string, feature = $dst_string))]
292              (Value::[<Matrix $src:camel>](v), ValueKind::Matrix(target_kind, dims)) if matches!(target_kind.as_ref(), ValueKind::[<$dst:camel>]) => {
293                if dims.is_empty() { 
294                  create_convert_mat_to_mat::<$src, $dst>(v, &shape)
295                } else if ((shape[0] == dims[0]) && (shape[1] == dims[1])) {
296                  create_convert_mat_to_mat::<$src, $dst>(v, &dims)
297                } else if shape[0] * shape[1] == dims[0] * dims[1] {
298                  create_reshape_mat_to_mat::<$src, $dst>(v, &dims)
299                } else {
300                  Err(MechError::new(UnsupportedConversionError{from: source_value.kind(), to: target_kind.as_ref().clone()}, None).with_compiler_loc())
301                }
302              }
303            )+
304          )+
305          _ => Err(MechError::new(UnsupportedConversionError{from: source_value.kind(), to: target_kind.clone()}, None).with_compiler_loc()),
306        }
307      }
308    }
309  };
310}
311
312#[cfg(not(target_arch = "wasm32"))]
313impl_conversion_mat_to_mat_fxn! {
314  f64, "f64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128", R64, "rational"];
315  f32, "f32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128", R64, "rational"];
316  u8,  "u8"  => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
317  u16, "u16" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
318  u32, "u32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
319  u64, "u64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
320  u128,"u128"=> [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
321  i8,  "i8"  => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
322  i16, "i16" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
323  i32, "i32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
324  i64, "i64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
325  i128,"i128"=> [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
326  bool, "bool" => [bool, "bool", String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
327  String, "string" => [String, "string"];
328  R64, "rational" => [String, "string"];
329  C64, "complex" => [String, "string"];
330}
331
332
333#[cfg(target_arch = "wasm32")]
334impl_conversion_mat_to_mat_fxn! {
335  f64, "f64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64", R64, "rational"];
336  f32, "f32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64", R64, "rational"];
337  u8,  "u8"  => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
338  u16, "u16" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
339  u32, "u32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
340  u64, "u64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
341  i8,  "i8"  => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
342  i16, "i16" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
343  i32, "i32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
344  i64, "i64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
345  bool, "bool" => [bool, "bool", String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
346  String, "string" => [String, "string"];
347  R64, "rational" => [String, "string"];
348  C64, "complex" => [String, "string"];
349}
350
351pub struct ConvertMatToMat {}
352
353impl NativeFunctionCompiler for ConvertMatToMat {
354  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
355    if arguments.len() != 2 {
356      return Err(MechError::new(IncorrectNumberOfArguments { expected: 2, found: arguments.len() }, None).with_compiler_loc());
357    }
358    let source_value = arguments[0].clone();
359    let source_kind = source_value.kind();
360    let target_kind = arguments[1].kind();
361    match impl_conversion_mat_to_mat_fxn(source_value.clone(), target_kind.clone()) {
362      Ok(fxn) => Ok(fxn),
363      Err(_) => {
364        match source_value {
365          Value::MutableReference(rhs) => impl_conversion_mat_to_mat_fxn(rhs.borrow().clone(), target_kind.clone()),
366          x => Err(MechError::new(
367              UnhandledFunctionArgumentKind2 { arg: (arguments[0].kind(), arguments[1].kind()), fxn_name: "convert/mat-to-mat".to_string() },
368              None
369            ).with_compiler_loc()
370          ),
371        }
372      }
373    }
374  }
375}
376
377
378
379#[derive(Debug, Clone)]
380pub struct ReshapeError {
381  pub requested: (usize, usize),
382  pub original: (usize, usize),
383}
384impl MechErrorKind for ReshapeError {
385  fn name(&self) -> &str { "ReshapeError" }
386  fn message(&self) -> String {
387    format!("Cannot reshape matrix of shape {:?} into {:?}",self.original,self.requested)
388  }
389}