1#![feature(step_trait)]
2use crate::*;
3use mech_core::*;
4use std::iter::Step;
5use nalgebra::{
6 base::{Matrix as naMatrix, Storage, StorageMut},
7 Dim, Scalar,
8};
9use mech_core::matrix::Matrix;
10use std::marker::PhantomData;
11
12#[derive(Debug)]
15pub struct RangeExclusiveScalar<T, MatA> {
16 pub from: Ref<T>,
17 pub to: Ref<T>,
18 pub out: Ref<MatA>,
19 phantom: PhantomData<T>,
20}
21impl<T, R1, C1, S1> MechFunctionFactory for RangeExclusiveScalar<T, naMatrix<T, R1, C1, S1>>
22where
23 T: Copy + Debug + Clone + Sync + Send + Step +
24 CompileConst + ConstElem + AsValueKind +
25 PartialOrd + 'static + One + Add<Output = T>,
26 Ref<naMatrix<T, R1, C1, S1>>: ToValue,
27 naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
28 R1: Dim + 'static, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug + 'static,
29{
30 fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
31 match args {
32 FunctionArgs::Binary(out, from, to) => {
33 let from: Ref<T> = unsafe { from.as_unchecked() }.clone();
34 let to: Ref<T> = unsafe { to.as_unchecked() }.clone();
35 let out: Ref<naMatrix<T, R1, C1, S1>> = unsafe { out.as_unchecked() }.clone();
36 Ok(Box::new(Self { from, to, out, phantom: PhantomData::default() }))
37 },
38 _ => Err(MechError{file: file!().to_string(), tokens: vec![], msg: format!("RangeExclusiveScalar requires 3 arguments, got {:?}", args), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments})
39 }
40 }
41}
42impl<T, R1, C1, S1> MechFunctionImpl for RangeExclusiveScalar<T, naMatrix<T, R1, C1, S1>>
43where
44 Ref<naMatrix<T, R1, C1, S1>>: ToValue,
45 T: Scalar + Clone + Debug + Sync + Send + 'static + PartialOrd + One + Add<Output = T> + 'static,
46 R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
47{
48 fn solve(&self) {
49 let from_ptr = self.from.as_ptr();
50 let to_ptr = self.to.as_ptr();
51 let out_ptr = self.out.as_mut_ptr();
52 let mut current = from_ptr;
53 unsafe {
54 for val in (*out_ptr).iter_mut() {
55 *val = (*current).clone();
56 current = &(*current).clone().add(T::one());
57 }
58 }
59 }
60 fn out(&self) -> Value { self.out.to_value() }
61 fn to_string(&self) -> String { format!("{:#?}", self) }
62}
63#[cfg(feature = "compiler")]
64impl<T, R1, C1, S1> MechFunctionCompiler for RangeExclusiveScalar<T, naMatrix<T, R1, C1, S1>>
65where
66 T: CompileConst + ConstElem + AsValueKind,
67 naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
68{
69 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
70 let name = format!("RangeExclusiveScalar<{}{}>", T::as_value_kind(), naMatrix::<T, R1, C1, S1>::as_na_kind());
71 compile_binop!(name, self.out, self.from, self.to, ctx, FeatureFlag::Builtin(FeatureKind::RangeExclusive) );
72 }
73}
74
75#[macro_export]
76macro_rules! impl_range_exclusive_match_arms {
77 ($fxn:ident, $arg1:expr, $arg2:expr, $($ty:tt, $feat:tt);+ $(;)?) => {
78 paste! {
79 match ($arg1, $arg2) {
80 $(
81 #[cfg(feature = $feat)]
82 (Value::[<$ty:camel>](from), Value::[<$ty:camel>](to)) => {
83 let from_val = *from.borrow();
84 let to_val = *to.borrow();
85 let diff = to_val - from_val;
86 if diff < $ty::zero() {
87 return Err(MechError {file: file!().to_string(),tokens: vec![],msg: "Range size must be > 0".to_string(),id: line!(),kind: MechErrorKind::UnhandledFunctionArgumentKind,});
88 }
89 let size = diff.try_into().map_err(|_| MechError {file: file!().to_string(),tokens: vec![],msg: "Range size overflow".to_string(),id: line!(),kind: MechErrorKind::UnhandledFunctionArgumentKind,})?;
90 let mut vec = vec![from_val; size];
91 match size {
92 0 => Err(MechError {file: file!().to_string(),tokens: vec![],msg: "Range size must be > 0".to_string(),id: line!(),kind: MechErrorKind::UnhandledFunctionArgumentKind,}),
93 #[cfg(feature = "matrix1")]
94 1 => {
95 register_range!($fxn, $ty, $feat, Matrix1);
96 Ok(Box::new($fxn::<$ty,Matrix1<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(Matrix1::from_element(vec[0])), phantom: PhantomData::default()}))
97 }
98 #[cfg(all(not(feature = "matrix1"), feature = "matrixd") )]
99 1 => {
100 register_range!($fxn, $ty, $feat, DMatrix);
101 Ok(Box::new($fxn::<$ty,DMatrix<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(DMatrix::from_element(1,1,vec[0])), phantom: PhantomData::default()}))
102 }
103 #[cfg(feature = "row_vector2")]
104 2 => {
105 register_range!($fxn, $ty, $feat, RowVector2);
106 Ok(Box::new($fxn::<$ty,RowVector2<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(RowVector2::from_vec(vec)), phantom: PhantomData::default()}))
107 }
108 #[cfg(feature = "row_vector3")]
109 3 => {
110 register_range!($fxn, $ty, $feat, RowVector3);
111 Ok(Box::new($fxn::<$ty,RowVector3<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(RowVector3::from_vec(vec)), phantom: PhantomData::default()}))
112 }
113 #[cfg(feature = "row_vector4")]
114 4 => {
115 register_range!($fxn, $ty, $feat, RowVector4);
116 Ok(Box::new($fxn::<$ty,RowVector4<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(RowVector4::from_vec(vec)), phantom: PhantomData::default()}))
117 }
118 #[cfg(feature = "row_vectord")]
119 n => {
120 register_range!($fxn, $ty, $feat, RowDVector);
121 Ok(Box::new($fxn::<$ty,RowDVector<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(RowDVector::from_vec(vec)), phantom: PhantomData::default()}))
122 }
123 }
124 }
125 )+
126 x => Err(MechError {file: file!().to_string(),tokens: vec![],msg: format!("{:?}", x),id: line!(),kind: MechErrorKind::UnhandledFunctionArgumentKind,})
127 }
128 }
129 }
130}
131
132fn impl_range_exclusive_fxn(arg1_value: Value, arg2_value: Value) -> MResult<Box<dyn MechFunction>> {
133 impl_range_exclusive_match_arms!(RangeExclusiveScalar, arg1_value, arg2_value,
134 F32, "f32";
135 F64, "f64";
136 i8, "i8";
137 i16, "i16";
138 i32, "i32";
139 i64, "i64";
140 i128,"i128";
141 u8, "u8";
142 u16, "u16";
143 u32, "u32";
144 u64, "u64";
145 u128,"u128";
146 )
147}
148
149pub struct RangeExclusive {}
150
151impl NativeFunctionCompiler for RangeExclusive {
152 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
153 if arguments.len() != 2 {
154 return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
155 }
156 let arg1 = arguments[0].clone();
157 let arg2 = arguments[1].clone();
158 match impl_range_exclusive_fxn(arg1.clone(), arg2.clone()) {
159 Ok(fxn) => Ok(fxn),
160 Err(_) => {
161 match (arg1,arg2) {
162 (Value::MutableReference(arg1),Value::MutableReference(arg2)) => {impl_range_exclusive_fxn(arg1.borrow().clone(),arg2.borrow().clone())}
163 (Value::MutableReference(arg1),arg2) => {impl_range_exclusive_fxn(arg1.borrow().clone(),arg2.clone())}
164 (arg1,Value::MutableReference(arg2)) => {impl_range_exclusive_fxn(arg1.clone(),arg2.borrow().clone())}
165 x => Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
166 }
167 }
168 }
169 }
170}
171
172register_descriptor! {
173 FunctionCompilerDescriptor {
174 name: "range/exclusive",
175 ptr: &RangeExclusive{},
176 }
177}