Skip to main content

mech_range/
exclusive_increment.rs

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// Exclusive ------------------------------------------------------------------
13
14#[derive(Debug)]
15pub struct RangeIncrementExclusiveScalar<T, MatA> {
16  pub from: Ref<T>,
17  pub step: Ref<T>,
18  pub to: Ref<T>,
19  pub out: Ref<MatA>,
20  phantom: PhantomData<T>,
21}
22impl<T, R1, C1, S1> MechFunctionFactory for RangeIncrementExclusiveScalar<T, naMatrix<T, R1, C1, S1>>
23where
24  T: Copy + Debug + Clone + Sync + Send + 
25  CompileConst + ConstElem + AsValueKind +
26  PartialOrd + 'static + One + Add<Output = T>,
27  Ref<naMatrix<T, R1, C1, S1>>: ToValue,
28  naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
29  R1: Dim + 'static, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug + 'static,
30{
31  fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
32    match args {
33      FunctionArgs::Ternary(out, from, step, to) => {
34        let from: Ref<T> = unsafe { from.as_unchecked() }.clone();
35        let step: Ref<T> = unsafe { step.as_unchecked() }.clone();
36        let to: Ref<T> = unsafe { to.as_unchecked() }.clone();
37        let out: Ref<naMatrix<T, R1, C1, S1>> = unsafe { out.as_unchecked() }.clone();
38        Ok(Box::new(Self { from, step, to, out, phantom: PhantomData::default() }))
39      },
40      _ => Err(MechError2::new(
41          IncorrectNumberOfArguments { expected: 3, found: args.len() },
42          None
43        ).with_compiler_loc()
44      ),
45    }
46  }
47}
48impl<T, R1, C1, S1> MechFunctionImpl for RangeIncrementExclusiveScalar<T, naMatrix<T, R1, C1, S1>>
49where
50  Ref<naMatrix<T, R1, C1, S1>>: ToValue,
51  T: Copy + Scalar + Clone + Debug + Sync + Send + 'static + PartialOrd + One + Add<Output = T> + 'static,
52  R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
53{
54  fn solve(&self) {
55    unsafe {
56      let out_ptr = self.out.as_ptr() as *mut naMatrix<T, R1, C1, S1>;
57      let mut current = *self.from.as_ptr();
58      let step = *self.step.as_ptr();
59      for i in 0..(*out_ptr).len() {
60        (&mut (*out_ptr))[i] = current;
61        current = current + step;
62      }
63    }
64  }
65  fn out(&self) -> Value { self.out.to_value() }
66  fn to_string(&self) -> String { format!("{:#?}", self) }
67}
68#[cfg(feature = "compiler")]
69impl<T, R1, C1, S1> MechFunctionCompiler for RangeIncrementExclusiveScalar<T, naMatrix<T, R1, C1, S1>> 
70where
71  T: CompileConst + ConstElem + AsValueKind,
72  naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
73{
74  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
75    let name = format!("RangeIncrementExclusiveScalar<{}{}>", T::as_value_kind(), naMatrix::<T, R1, C1, S1>::as_na_kind());
76    compile_ternop!(name, self.out, self.from, self.step, self.to, ctx, FeatureFlag::Builtin(FeatureKind::RangeExclusive) );
77  }
78}
79
80#[macro_export]
81macro_rules! impl_range_increment_exclusive_match_arms {
82  ($fxn:ident, $arg1:expr, $arg2:expr, $arg3:expr, $($ty:tt, $feat:tt);+ $(;)?) => {
83    paste! {
84      match ($arg1, $arg2, $arg3) {
85        $(
86          #[cfg(feature = $feat)]
87          (Value::[<$ty:camel>](from), Value::[<$ty:camel>](step), Value::[<$ty:camel>](to))  => {
88            let from_val = *from.borrow();
89            let step_val = *step.borrow();
90            let to_val = *to.borrow();
91            let diff = to_val - from_val;
92            if diff < $ty::zero() {
93              return Err(MechError2::new(
94                EmptyRangeError{},
95                None
96              ).with_compiler_loc());
97            }
98            let size = {
99              let diff = to_val as f64 - from_val as f64;
100              let step = step_val as f64;
101              if step == 0.0 {
102                return Err(MechError2::new(EmptyRangeError {}, None).with_compiler_loc());
103              }
104              if (diff > 0.0 && step > 0.0) || (diff < 0.0 && step < 0.0) {
105                (diff / step).ceil() as usize
106              } else {
107                0
108              }
109            };
110            let mut vec = vec![from_val; size];
111            match size {
112              0 => Err(MechError2::new(
113                EmptyRangeError{},
114                None
115              ).with_compiler_loc()),
116              #[cfg(feature = "matrix1")]
117              1 => {
118                register_range!($fxn, $ty, $feat, Matrix1);
119                Ok(Box::new($fxn::<$ty,Matrix1<$ty>>{from: from.clone(), step: step.clone(), to: to.clone(), out: Ref::new(Matrix1::from_element(vec[0])), phantom: PhantomData::default()}))
120              }
121              #[cfg(all(not(feature = "matrix1"), feature = "matrixd")  )]
122              1 => {
123                register_range!($fxn, $ty, $feat, DMatrix);
124                Ok(Box::new($fxn::<$ty,DMatrix<$ty>>{from: from.clone(), step: step.clone(), to: to.clone(), out: Ref::new(DMatrix::from_element(1,1,vec[0])), phantom: PhantomData::default()}))
125              }
126              #[cfg(feature = "row_vector2")]
127              2 => {
128                register_range!($fxn, $ty, $feat, RowVector2);
129                Ok(Box::new($fxn::<$ty,RowVector2<$ty>>{from: from.clone(), step: step.clone(), to: to.clone(), out: Ref::new(RowVector2::from_vec(vec)), phantom: PhantomData::default()}))
130              }
131              #[cfg(feature = "row_vector3")]
132              3 => {              
133                register_range!($fxn, $ty, $feat, RowVector3);
134                Ok(Box::new($fxn::<$ty,RowVector3<$ty>>{from: from.clone(), step: step.clone(), to: to.clone(), out: Ref::new(RowVector3::from_vec(vec)), phantom: PhantomData::default()}))
135              }
136              #[cfg(feature = "row_vector4")]
137              4 => {
138                register_range!($fxn, $ty, $feat, RowVector4);
139                Ok(Box::new($fxn::<$ty,RowVector4<$ty>>{from: from.clone(), step: step.clone(), to: to.clone(), out: Ref::new(RowVector4::from_vec(vec)), phantom: PhantomData::default()}))
140              }
141              #[cfg(feature = "row_vectord")]
142              n => {
143                register_range!($fxn, $ty, $feat, RowDVector);
144                Ok(Box::new($fxn::<$ty,RowDVector<$ty>>{from: from.clone(), step: step.clone(), to: to.clone(), out: Ref::new(RowDVector::from_vec(vec)), phantom: PhantomData::default()}))
145              }
146            }
147          }
148        )+
149        (arg1,arg2,arg3) => Err(MechError2::new(
150          UnhandledFunctionArgumentKind3 {arg: (arg1.kind(),arg2.kind(), arg3.kind()), fxn_name: stringify!($fxn).to_string() },
151          None
152        ).with_compiler_loc()),
153      }
154    }
155  }
156}
157
158fn impl_range_increment_exclusive_fxn(arg1_value: Value, arg2_value: Value, arg3_value: Value) -> MResult<Box<dyn MechFunction>> {
159  impl_range_increment_exclusive_match_arms!(RangeIncrementExclusiveScalar, arg1_value, arg2_value, arg3_value,
160    f32, "f32";
161    f64, "f64";
162    i8,  "i8";
163    i16, "i16";
164    i32, "i32";
165    i64, "i64";
166    i128,"i128";
167    u8,  "u8";
168    u16, "u16";
169    u32, "u32";
170    u64, "u64";
171    u128,"u128";
172  )
173}
174
175pub struct RangeIncrementExclusive {}
176
177impl NativeFunctionCompiler for RangeIncrementExclusive {
178  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
179    if arguments.len() != 3 {
180      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 3, found: arguments.len() },None).with_compiler_loc());
181    }
182    let arg1 = arguments[0].clone();
183    let arg2 = arguments[1].clone();
184    let arg3 = arguments[2].clone();
185    match impl_range_increment_exclusive_fxn(arg1.clone(), arg2.clone(), arg3.clone()) {
186      Ok(fxn) => Ok(fxn),
187      Err(_) => {
188        match (arg1, arg2, arg3) {
189          (Value::MutableReference(arg1), Value::MutableReference(arg2), Value::MutableReference(arg3)) => {
190            impl_range_increment_exclusive_fxn(arg1.borrow().clone(), arg2.borrow().clone(), arg3.borrow().clone())
191          }
192          (Value::MutableReference(arg1), Value::MutableReference(arg2), arg3) => {
193            impl_range_increment_exclusive_fxn(arg1.borrow().clone(), arg2.borrow().clone(), arg3.clone())
194          }
195          (Value::MutableReference(arg1), arg2, Value::MutableReference(arg3)) => {
196            impl_range_increment_exclusive_fxn(arg1.borrow().clone(), arg2.clone(), arg3.borrow().clone())
197          }
198          (Value::MutableReference(arg1), arg2, arg3) => {
199            impl_range_increment_exclusive_fxn(arg1.borrow().clone(), arg2.clone(), arg3.clone())
200          }
201          (arg1, Value::MutableReference(arg2), Value::MutableReference(arg3)) => {
202            impl_range_increment_exclusive_fxn(arg1.clone(), arg2.borrow().clone(), arg3.borrow().clone())
203          }
204          (arg1, Value::MutableReference(arg2), arg3) => {
205            impl_range_increment_exclusive_fxn(arg1.clone(), arg2.borrow().clone(), arg3.clone())
206          }
207          (arg1, arg2, Value::MutableReference(arg3)) => {
208            impl_range_increment_exclusive_fxn(arg1.clone(), arg2.clone(), arg3.borrow().clone())
209          }
210          (arg1, arg2, arg3) => Err(MechError2::new(
211            UnhandledFunctionArgumentKind3 { arg: (arg1.kind(), arg2.kind(), arg3.kind()), fxn_name: "range/exclusive-increment".to_string() },
212            None
213          ).with_compiler_loc()),
214        }
215      }
216    }
217  }
218}
219
220register_descriptor! {
221  FunctionCompilerDescriptor {
222    name: "range/exclusive-increment",
223    ptr: &RangeIncrementExclusive{},
224  }
225}