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 +
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(MechError2::new(
39 IncorrectNumberOfArguments { expected: 3, found: args.len() },
40 None
41 ).with_compiler_loc()
42 ),
43 }
44 }
45}
46impl<T, R1, C1, S1> MechFunctionImpl for RangeExclusiveScalar<T, naMatrix<T, R1, C1, S1>>
47where
48 Ref<naMatrix<T, R1, C1, S1>>: ToValue,
49 T: Scalar + Clone + Debug + Sync + Send + 'static + PartialOrd + One + Add<Output = T> + 'static,
50 R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
51{
52 fn solve(&self) {
53 let from_ptr = self.from.as_ptr();
54 let to_ptr = self.to.as_ptr();
55 let out_ptr = self.out.as_mut_ptr();
56 let mut current = from_ptr;
57 unsafe {
58 for val in (*out_ptr).iter_mut() {
59 *val = (*current).clone();
60 current = &(*current).clone().add(T::one());
61 }
62 }
63 }
64 fn out(&self) -> Value { self.out.to_value() }
65 fn to_string(&self) -> String { format!("{:#?}", self) }
66}
67#[cfg(feature = "compiler")]
68impl<T, R1, C1, S1> MechFunctionCompiler for RangeExclusiveScalar<T, naMatrix<T, R1, C1, S1>>
69where
70 T: CompileConst + ConstElem + AsValueKind,
71 naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
72{
73 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
74 let name = format!("RangeExclusiveScalar<{}{}>", T::as_value_kind(), naMatrix::<T, R1, C1, S1>::as_na_kind());
75 compile_binop!(name, self.out, self.from, self.to, ctx, FeatureFlag::Builtin(FeatureKind::RangeExclusive) );
76 }
77}
78
79#[macro_export]
80macro_rules! impl_range_exclusive_match_arms {
81 ($fxn:ident, $arg1:expr, $arg2:expr, $($ty:tt, $feat:tt);+ $(;)?) => {
82 paste! {
83 match ($arg1, $arg2) {
84 $(
85 #[cfg(feature = $feat)]
86 (Value::[<$ty:camel>](from), Value::[<$ty:camel>](to)) => {
87 let from_val = *from.borrow();
88 let to_val = *to.borrow();
89 let diff = to_val - from_val;
90 if diff < $ty::zero() {
91 return Err(MechError2::new(
92 EmptyRangeError{},
93 None
94 ).with_compiler_loc());
95 }
96 let size = range_size_to_usize!(diff, $ty);
97 let mut vec = vec![from_val; size];
98 match size {
99 0 => Err(MechError2::new(
100 EmptyRangeError{},
101 None
102 ).with_compiler_loc()),
103 #[cfg(feature = "matrix1")]
104 1 => {
105 register_range!($fxn, $ty, $feat, Matrix1);
106 Ok(Box::new($fxn::<$ty,Matrix1<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(Matrix1::from_element(vec[0])), phantom: PhantomData::default()}))
107 }
108 #[cfg(all(not(feature = "matrix1"), feature = "matrixd") )]
109 1 => {
110 register_range!($fxn, $ty, $feat, DMatrix);
111 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()}))
112 }
113 #[cfg(feature = "row_vector2")]
114 2 => {
115 register_range!($fxn, $ty, $feat, RowVector2);
116 Ok(Box::new($fxn::<$ty,RowVector2<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(RowVector2::from_vec(vec)), phantom: PhantomData::default()}))
117 }
118 #[cfg(feature = "row_vector3")]
119 3 => {
120 register_range!($fxn, $ty, $feat, RowVector3);
121 Ok(Box::new($fxn::<$ty,RowVector3<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(RowVector3::from_vec(vec)), phantom: PhantomData::default()}))
122 }
123 #[cfg(feature = "row_vector4")]
124 4 => {
125 register_range!($fxn, $ty, $feat, RowVector4);
126 Ok(Box::new($fxn::<$ty,RowVector4<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(RowVector4::from_vec(vec)), phantom: PhantomData::default()}))
127 }
128 #[cfg(feature = "row_vectord")]
129 n => {
130 register_range!($fxn, $ty, $feat, RowDVector);
131 Ok(Box::new($fxn::<$ty,RowDVector<$ty>>{from: from.clone(), to: to.clone(), out: Ref::new(RowDVector::from_vec(vec)), phantom: PhantomData::default()}))
132 }
133 }
134 }
135 )+
136 (arg1,arg2) => Err(MechError2::new(
137 UnhandledFunctionArgumentKind2 {arg: (arg1.kind(),arg2.kind()), fxn_name: stringify!($fxn).to_string() },
138 None
139 ).with_compiler_loc()),
140 }
141 }
142 }
143}
144
145fn impl_range_exclusive_fxn(arg1_value: Value, arg2_value: Value) -> MResult<Box<dyn MechFunction>> {
146 impl_range_exclusive_match_arms!(RangeExclusiveScalar, arg1_value, arg2_value,
147 f32, "f32";
148 f64, "f64";
149 i8, "i8";
150 i16, "i16";
151 i32, "i32";
152 i64, "i64";
153 i128,"i128";
154 u8, "u8";
155 u16, "u16";
156 u32, "u32";
157 u64, "u64";
158 u128,"u128";
159 )
160}
161
162pub struct RangeExclusive {}
163
164impl NativeFunctionCompiler for RangeExclusive {
165 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
166 if arguments.len() != 2 {
167 return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
168 }
169 let arg1 = arguments[0].clone();
170 let arg2 = arguments[1].clone();
171 match impl_range_exclusive_fxn(arg1.clone(), arg2.clone()) {
172 Ok(fxn) => Ok(fxn),
173 Err(_) => {
174 match (arg1,arg2) {
175 (Value::MutableReference(arg1),Value::MutableReference(arg2)) => {impl_range_exclusive_fxn(arg1.borrow().clone(),arg2.borrow().clone())}
176 (Value::MutableReference(arg1),arg2) => {impl_range_exclusive_fxn(arg1.borrow().clone(),arg2.clone())}
177 (arg1,Value::MutableReference(arg2)) => {impl_range_exclusive_fxn(arg1.clone(),arg2.borrow().clone())}
178 (arg1,arg2) => Err(MechError2::new(
179 UnhandledFunctionArgumentKind2 { arg: (arg1.kind(),arg2.kind()), fxn_name: "range/exclusive".to_string() },
180 None
181 ).with_compiler_loc()
182 ),
183 }
184 }
185 }
186 }
187}
188
189register_descriptor! {
190 FunctionCompilerDescriptor {
191 name: "range/exclusive",
192 ptr: &RangeExclusive{},
193 }
194}