1use crate::*;
2use mech_core::*;
3#[cfg(feature = "matrix")]
4use mech_core::matrix::Matrix;
5
6macro_rules! transpose_op {
9 ($arg:expr, $out:expr) => {
10 unsafe { *$out = (*$arg).transpose(); }
11 };}
12
13#[macro_export]
14macro_rules! impl_transpose {
15 ($struct_name:ident, $arg_type:ty, $out_type:ty, $op:ident, $feature_flag:expr) => {
16 #[derive(Debug)]
17 struct $struct_name<T> {
18 arg: Ref<$arg_type>,
19 out: Ref<$out_type>,
20 }
21 impl<T> MechFunctionFactory for $struct_name<T>
22 where
23 T: Debug + Clone + Sync + Send + 'static +
24 ConstElem + CompileConst + AsValueKind +
25 PartialEq + PartialOrd,
26 Ref<$out_type>: ToValue
27 {
28 fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
29 match args {
30 FunctionArgs::Unary(out, arg) => {
31 let arg: Ref<$arg_type> = unsafe{ arg.as_unchecked().clone() };
32 let out: Ref<$out_type> = unsafe{ out.as_unchecked().clone() };
33 Ok(Box::new($struct_name{arg, out}))
34 }
35 _ => Err(MechError{file: file!().to_string(), tokens: vec![], msg: format!("Expected unary arguments, got {:#?}", args), id: line!(), kind: MechErrorKind::None }),
36 }
37 }
38 }
39 impl<T> MechFunctionImpl for $struct_name<T>
40 where
41 T: Debug + Clone + Sync + Send + 'static +
42 PartialEq + PartialOrd,
43 Ref<$out_type>: ToValue
44 {
45 fn solve(&self) {
46 let arg_ptr = self.arg.as_ptr();
47 let out_ptr = self.out.as_mut_ptr();
48 $op!(arg_ptr,out_ptr);
49 }
50 fn out(&self) -> Value { self.out.to_value() }
51 fn to_string(&self) -> String { format!("{:#?}", self) }
52 }
53 #[cfg(feature = "compiler")]
54 impl<T> MechFunctionCompiler for $struct_name<T>
55 where
56 T: ConstElem + CompileConst + AsValueKind,
57 {
58 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
59 let name = format!("{}<{}>", stringify!($struct_name), T::as_value_kind());
60 compile_unop!(name, self.out, self.arg, ctx, $feature_flag);
61 }
62 }
63 register_fxn_descriptor!($struct_name, u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128", F32, "f32", F64, "f64", bool, "bool", String, "string", C64, "complex", R64, "rational");
64 };
65}
66
67#[cfg(feature = "matrix1")]
68impl_transpose!(TransposeM1, Matrix1<T>, Matrix1<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
69#[cfg(feature = "matrix2")]
70impl_transpose!(TransposeM2, Matrix2<T>, Matrix2<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
71#[cfg(feature = "matrix3")]
72impl_transpose!(TransposeM3, Matrix3<T>, Matrix3<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
73#[cfg(feature = "matrix4")]
74impl_transpose!(TransposeM4, Matrix4<T>, Matrix4<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
75#[cfg(all(feature = "matrix2x3", feature = "matrix3x2"))]
76impl_transpose!(TransposeM2x3, Matrix2x3<T>, Matrix3x2<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
77#[cfg(all(feature = "matrix3x2", feature = "matrix2x3"))]
78impl_transpose!(TransposeM3x2, Matrix3x2<T>, Matrix2x3<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
79#[cfg(feature = "matrixd")]
80impl_transpose!(TransposeMD, DMatrix<T>, DMatrix<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
81#[cfg(all(feature = "vector2", feature = "row_vector2"))]
82impl_transpose!(TransposeV2, Vector2<T>, RowVector2<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
83#[cfg(all(feature = "vector3", feature = "row_vector3"))]
84impl_transpose!(TransposeV3, Vector3<T>, RowVector3<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
85#[cfg(all(feature = "vector4", feature = "row_vector4"))]
86impl_transpose!(TransposeV4, Vector4<T>, RowVector4<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
87#[cfg(all(feature = "vectord", feature = "row_vectord"))]
88impl_transpose!(TransposeVD, DVector<T>, RowDVector<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
89#[cfg(all(feature = "row_vector2", feature = "vector2"))]
90impl_transpose!(TransposeR2, RowVector2<T>, Vector2<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
91#[cfg(all(feature = "row_vector3", feature = "vector3"))]
92impl_transpose!(TransposeR3, RowVector3<T>, Vector3<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
93#[cfg(all(feature = "row_vector4", feature = "vector4"))]
94impl_transpose!(TransposeR4, RowVector4<T>, Vector4<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
95#[cfg(all(feature = "row_vectord", feature = "vectord"))]
96impl_transpose!(TransposeRD, RowDVector<T>, DVector<T>, transpose_op, FeatureFlag::Builtin(FeatureKind::Transpose));
97
98macro_rules! impl_transpose_match_arms {
99 ($arg:expr, $($input_type:ident, $($target_type:ident, $value_string:tt),+);+ $(;)?) => {
100 paste!{
101 match $arg {
102 $(
103 $(
104 #[cfg(all(feature = "row_vector4", feature = "vector4", feature = $value_string))]
105 Value::[<Matrix $input_type>](Matrix::<$target_type>::RowVector4(arg)) => Ok(Box::new(TransposeR4{arg: arg.clone(), out: Ref::new(Vector4::from_element($target_type::default())) })),
106 #[cfg(all(feature = "row_vector3", feature = "vector3", feature = $value_string))]
107 Value::[<Matrix $input_type>](Matrix::<$target_type>::RowVector3(arg)) => Ok(Box::new(TransposeR3{arg: arg.clone(), out: Ref::new(Vector3::from_element($target_type::default())) })),
108 #[cfg(all(feature = "row_vector2", feature = "vector2", feature = $value_string))]
109 Value::[<Matrix $input_type>](Matrix::<$target_type>::RowVector2(arg)) => Ok(Box::new(TransposeR2{arg: arg.clone(), out: Ref::new(Vector2::from_element($target_type::default())) })),
110 #[cfg(all(feature = "vector4", feature = "row_vector4", feature = $value_string))]
111 Value::[<Matrix $input_type>](Matrix::<$target_type>::Vector4(arg)) => Ok(Box::new(TransposeV4{arg: arg.clone(), out: Ref::new(RowVector4::from_element($target_type::default())) })),
112 #[cfg(all(feature = "vector3", feature = "row_vector3", feature = $value_string))]
113 Value::[<Matrix $input_type>](Matrix::<$target_type>::Vector3(arg)) => Ok(Box::new(TransposeV3{arg: arg.clone(), out: Ref::new(RowVector3::from_element($target_type::default())) })),
114 #[cfg(all(feature = "vector2", feature = "row_vector2", feature = $value_string))]
115 Value::[<Matrix $input_type>](Matrix::<$target_type>::Vector2(arg)) => Ok(Box::new(TransposeV2{arg: arg.clone(), out: Ref::new(RowVector2::from_element($target_type::default())) })),
116 #[cfg(all(feature = "matrix4", feature = $value_string))]
117 Value::[<Matrix $input_type>](Matrix::<$target_type>::Matrix4(arg)) => Ok(Box::new(TransposeM4{arg: arg.clone(), out: Ref::new(Matrix4::from_element($target_type::default()))})),
118 #[cfg(all(feature = "matrix3", feature = $value_string))]
119 Value::[<Matrix $input_type>](Matrix::<$target_type>::Matrix3(arg)) => Ok(Box::new(TransposeM3{arg: arg.clone(), out: Ref::new(Matrix3::from_element($target_type::default()))})),
120 #[cfg(all(feature = "matrix2", feature = $value_string))]
121 Value::[<Matrix $input_type>](Matrix::<$target_type>::Matrix2(arg)) => Ok(Box::new(TransposeM2{arg: arg.clone(), out: Ref::new(Matrix2::from_element($target_type::default()))})),
122 #[cfg(all(feature = "matrix1", feature = $value_string))]
123 Value::[<Matrix $input_type>](Matrix::<$target_type>::Matrix1(arg)) => Ok(Box::new(TransposeM1{arg: arg.clone(), out: Ref::new(Matrix1::from_element($target_type::default()))})),
124 #[cfg(all(feature = "matrix2x3", feature = "matrix3x2", feature = $value_string))]
125 Value::[<Matrix $input_type>](Matrix::<$target_type>::Matrix2x3(arg)) => Ok(Box::new(TransposeM2x3{arg: arg.clone(), out: Ref::new(Matrix3x2::from_element($target_type::default()))})),
126 #[cfg(all(feature = "matrix3x2", feature = "matrix2x3", feature = $value_string))]
127 Value::[<Matrix $input_type>](Matrix::<$target_type>::Matrix3x2(arg)) => Ok(Box::new(TransposeM3x2{arg: arg.clone(), out: Ref::new(Matrix2x3::from_element($target_type::default()))})),
128 #[cfg(all(feature = "vectord", feature = "row_vectord", feature = $value_string))]
129 Value::[<Matrix $input_type>](Matrix::<$target_type>::DVector(arg)) => Ok(Box::new(TransposeVD{arg: arg.clone(), out: Ref::new(RowDVector::from_element(arg.borrow().len(),$target_type::default())) })),
130 #[cfg(all(feature = "vectord", feature = "row_vectord", feature = $value_string))]
131 Value::[<Matrix $input_type>](Matrix::<$target_type>::RowDVector(arg)) => Ok(Box::new(TransposeRD{arg: arg.clone(), out: Ref::new(DVector::from_element(arg.borrow().len(),$target_type::default())) })),
132 #[cfg(all(feature = "matrixd", feature = $value_string))]
133 Value::[<Matrix $input_type>](Matrix::<$target_type>::DMatrix(arg)) => {
134 let (rows,cols) = {arg.borrow().shape()};
135 Ok(Box::new(TransposeMD{arg, out: Ref::new(DMatrix::from_element(rows,cols,$target_type::default()))}))
136 },
137 )+
138 )+
139 x => Err(MechError{file: file!().to_string(), tokens: vec![], msg: format!("{:#?}", x), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
140 }
141 }
142 }
143}
144
145fn impl_transpose_fxn(lhs_value: Value) -> Result<Box<dyn MechFunction>, MechError> {
146 impl_transpose_match_arms!(
147 (lhs_value),
148 Bool, bool, "bool";
149 I8, i8, "i8";
150 I16, i16, "i16";
151 I32, i32, "i32";
152 I64, i64, "i64";
153 I128, i128, "i128";
154 U8, u8, "u8";
155 U16, u16, "u16";
156 U32, u32, "u32";
157 U64, u64, "u64";
158 U128, u128, "u128";
159 F32, F32, "f32";
160 F64, F64, "f64";
161 String, String, "string";
162 C64, C64, "complex";
163 R64, R64, "rational";
164 )
165}
166
167impl_mech_urnop_fxn!(MatrixTranspose,impl_transpose_fxn,"matrix/transpose");