mech_interpreter/stdlib/convert/
scalar_to_mat.rs1#[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}