mech_interpreter/stdlib/convert/
scalar_to_mat.rs

1#[macro_use]
2use crate::stdlib::*;
3use nalgebra::Scalar;
4use std::marker::PhantomData;
5
6#[derive(Debug)]
7pub struct ConvertScalarToMat2<F, T> {
8  pub arg: Ref<F>,
9  pub out: Ref<T>,
10}
11
12impl<F, T> MechFunctionImpl for ConvertScalarToMat2<F, T>
13where
14  Ref<T>: ToValue,
15  F: Debug + Scalar + Clone,
16  for<'a> &'a mut T: IntoIterator<Item = &'a mut F>,
17  T: Debug,
18{
19  fn solve(&self) {
20    let arg_ptr = self.arg.as_ptr();
21    let out_ptr = self.out.as_mut_ptr();
22    unsafe {
23      let arg_ref: &F = &*arg_ptr;
24      let out_ref: &mut T = &mut *out_ptr;
25      for dst in (&mut *out_ref).into_iter() {
26        *dst = arg_ref.clone();
27      }
28    }
29  }
30  fn out(&self) -> Value {self.out.to_value()}
31  fn to_string(&self) -> String { format!("{:#?}",self) }
32}
33#[cfg(feature = "compiler")]
34impl<F, T> MechFunctionCompiler for ConvertScalarToMat2<F, T>
35where
36  T: CompileConst + ConstElem + AsValueKind,
37  F: ConstElem + CompileConst + AsValueKind,
38{
39  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
40    let name = format!("ConvertScalarToMat2<{},{}>", F::as_value_kind(), T::as_value_kind());
41    compile_unop!(name, self.out, self.arg, ctx, FeatureFlag::Builtin(FeatureKind::Convert));
42  }
43}
44
45macro_rules! impl_conversion_scalar_to_mat_match_arms {
46  ($arg:expr, $($input_type:ident => $($target_type:ident, $type_string:tt),+);+ $(;)?) => {
47    paste!{
48      match $arg {
49        $(
50          $(
51            #[cfg(all(feature = "matrix", feature = $type_string))]
52            (Value::$input_type(v), ValueKind::Matrix(box ValueKind::$target_type, dims)) => {
53              match dims[..] {
54                #[cfg(feature = "matrix1")]
55                [1,1] => {let out = Matrix1::from_element(v.borrow().clone());      return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
56                #[cfg(feature = "matrix2")]
57                [2,2] => {let out = Matrix2::from_element(v.borrow().clone());      return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
58                #[cfg(feature = "matrix3")]
59                [3,3] => {let out = Matrix3::from_element(v.borrow().clone());      return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
60                #[cfg(feature = "matrix4")]
61                [4,4] => {let out = Matrix4::from_element(v.borrow().clone());      return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
62                #[cfg(feature = "matrix2x3")]
63                [2,3] => {let out = Matrix2x3::from_element(v.borrow().clone());    return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
64                #[cfg(feature = "matrix3x2")]
65                [3,2] => {let out = Matrix3x2::from_element(v.borrow().clone());    return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
66                #[cfg(feature = "row_vector2")]
67                [1,2] => {let out = RowVector2::from_element(v.borrow().clone());   return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
68                #[cfg(feature = "row_vector3")]
69                [1,3] => {let out = RowVector3::from_element(v.borrow().clone());   return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
70                #[cfg(feature = "row_vector4")]
71                [1,4] => {let out = RowVector4::from_element(v.borrow().clone());   return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
72                #[cfg(feature = "vector2")]
73                [2,1] => {let out = Vector2::from_element(v.borrow().clone());      return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
74                #[cfg(feature = "vector3")]
75                [3,1] => {let out = Vector3::from_element(v.borrow().clone());      return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
76                #[cfg(feature = "vector4")]
77                [4,1] => {let out = Vector4::from_element(v.borrow().clone());      return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
78                #[cfg(feature = "row_vectord")]
79                [1,n] => {let out = RowDVector::from_element(n,v.borrow().clone()); return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
80                #[cfg(feature = "vectord")]
81                [n,1] => {let out = DVector::from_element(n,v.borrow().clone());    return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
82                #[cfg(feature = "matrixd")]
83                [n,m] => {let out = DMatrix::from_element(n,m,v.borrow().clone());  return Ok(Box::new(ConvertScalarToMat2{arg: v, out: Ref::new(out)}));},
84                [] => {return Err(MechError2::new(
85                  CannotReshapeMatrixToEmpty,
86                  None
87                ).with_compiler_loc());}
88                _ => todo!(),
89              }
90            }
91          )+
92        )+
93        x => Err(MechError2::new(
94            UnsupportedConversionError{from: x.0.kind(), to: x.1.clone()},
95            None
96          ).with_compiler_loc()
97        ),
98      }
99    }
100  }
101}
102
103fn impl_conversion_scalar_to_mat_fxn(source_value: Value, target_kind: ValueKind) -> MResult<Box<dyn MechFunction>>  {
104  impl_conversion_scalar_to_mat_match_arms!(
105    (source_value, target_kind),
106    Bool => Bool, "bool";
107    U8 => U8, "u8";
108    U16 => U16, "u16";
109    U32 => U32, "u32";
110    U64 => U64, "u64";
111    U128 => U128, "u128";
112    I8 => I8, "i8";
113    I16 => I16, "i16";
114    I32 => I32, "i32";
115    I64 => I64, "i64";
116    I128 => I128, "i128";
117    F32 => F32, "f32";
118    F64 => F64, "f64";
119    String => String, "string";
120    R64 => R64, "rational";
121    C64 => C64, "complex";
122  )
123}
124
125pub struct ConvertScalarToMat {}
126
127impl NativeFunctionCompiler for ConvertScalarToMat {
128  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
129    if arguments.len() != 2 {
130      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
131    }
132    let source_value = arguments[0].clone();
133    let source_kind = source_value.kind();
134    let target_kind = arguments[1].kind();
135    match impl_conversion_scalar_to_mat_fxn(source_value.clone(), target_kind.clone()) {
136      Ok(fxn) => Ok(fxn),
137      Err(_) => {
138        match source_value {
139          Value::MutableReference(rhs) => impl_conversion_scalar_to_mat_fxn(rhs.borrow().clone(), target_kind.clone()),
140          x => Err(MechError2::new(
141              UnhandledFunctionArgumentKind2 { arg: (arguments[0].kind(), arguments[1].kind()), fxn_name: "convert/scalar-to-mat".to_string() },
142              None,
143            ).with_compiler_loc()
144          ),
145        }
146      }
147    }
148  }
149}
150
151#[derive(Debug, Clone)]
152pub struct CannotReshapeMatrixToEmpty;
153
154impl MechErrorKind2 for CannotReshapeMatrixToEmpty {
155  fn name(&self) -> &str { "CannotReshapeMatrixToEmpty" }
156  fn message(&self) -> String {
157    "Cannot reshape matrix to empty dimensions".to_string()
158  }
159}