mech_math/op_assign/
mod.rs

1#[macro_use]
2use crate::*;
3
4use std::fmt::Debug;
5use std::marker::PhantomData;
6
7#[cfg(feature = "matrix")]
8use nalgebra::{
9  base::{Matrix as naMatrix, Storage, StorageMut},
10  Dim, Scalar,
11};
12
13#[cfg(feature = "add_assign")]
14pub mod add_assign;
15#[cfg(feature = "sub_assign")]
16pub mod sub_assign;
17#[cfg(feature = "div_assign")]
18pub mod div_assign;
19#[cfg(feature = "mul_assign")]
20pub mod mul_assign;
21
22#[cfg(feature = "add_assign")]
23pub use self::add_assign::*;
24#[cfg(feature = "sub_assign")]
25pub use self::sub_assign::*;
26#[cfg(feature = "div_assign")]
27pub use self::div_assign::*;
28#[cfg(feature = "mul_assign")]
29pub use self::mul_assign::*;
30
31#[macro_export]
32macro_rules! impl_op_assign_range_fxn_s {
33  ($struct_name:ident, $op:ident, $ix:ty) => {
34    #[derive(Debug)]
35    pub struct $struct_name<T, MatA, IxVec> {
36      pub source: Ref<T>,
37      pub ixes: Ref<IxVec>,
38      pub sink: Ref<MatA>,
39      pub _marker: PhantomData<T>,
40    }
41    impl<T, R1: 'static, C1: 'static, S1: 'static, IxVec: 'static> MechFunctionFactory for $struct_name<T, naMatrix<T, R1, C1, S1>, IxVec>
42    where
43      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
44      T: Copy + Debug + Clone + Sync + Send + 'static +
45        Div<Output = T> + DivAssign +
46        Add<Output = T> + AddAssign +
47        Sub<Output = T> + SubAssign +
48        Mul<Output = T> + MulAssign +
49        Zero + One +
50        PartialEq + PartialOrd +
51        CompileConst + ConstElem + AsValueKind,
52      IxVec: CompileConst + ConstElem + Debug + AsRef<[$ix]> + AsNaKind,
53      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
54      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + Debug + AsNaKind,
55    {
56      fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
57        match args {
58          FunctionArgs::Binary(out, arg1, arg2) => {
59            let source: Ref<T> = unsafe { arg1.as_unchecked() }.clone();
60            let ixes: Ref<IxVec> = unsafe { arg2.as_unchecked() }.clone();
61            let sink: Ref<naMatrix<T, R1, C1, S1>> = unsafe { out.as_unchecked() }.clone();
62            Ok(Box::new(Self { sink, source, ixes, _marker: PhantomData::default() }))
63          },
64          _ => Err(MechError{file: file!().to_string(), tokens: vec![], msg: format!("{} requires 3 arguments, got {:?}", stringify!($struct_name), args), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments})
65        }
66      }
67    }
68    impl<T, R1, C1, S1, IxVec> MechFunctionImpl for $struct_name<T, naMatrix<T, R1, C1, S1>, IxVec>
69    where
70      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
71      T: Copy + Debug + Clone + Sync + Send + 'static +
72        Div<Output = T> + DivAssign +
73        Add<Output = T> + AddAssign +
74        Sub<Output = T> + SubAssign +
75        Mul<Output = T> + MulAssign +
76        Zero + One +
77        PartialEq + PartialOrd,
78      IxVec: AsRef<[$ix]> + Debug,
79      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
80    {
81      fn solve(&self) {
82        unsafe {
83          let sink_ptr = &mut *self.sink.as_mut_ptr();
84          let source_ptr = &*self.source.as_ptr();
85          let ix_ptr = &(*self.ixes.as_ptr()).as_ref();
86          $op!(source_ptr,ix_ptr,sink_ptr);
87        }
88      }
89      fn out(&self) -> Value {self.sink.to_value()}
90      fn to_string(&self) -> String {format!("{:#?}", self)}
91    }
92    #[cfg(feature = "compiler")]
93    impl<T, R1, C1, S1, IxVec> MechFunctionCompiler for $struct_name<T, naMatrix<T, R1, C1, S1>, IxVec> 
94    where
95      T: CompileConst + ConstElem + AsValueKind,
96      IxVec: CompileConst + ConstElem + AsNaKind,
97      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
98    {
99      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
100        let name = format!("{}<{}{}{}>", stringify!($struct_name), T::as_value_kind(), naMatrix::<T, R1, C1, S1>::as_na_kind(), IxVec::as_na_kind());
101        compile_binop!(name, self.sink, self.source, self.ixes, ctx, FeatureFlag::Builtin(FeatureKind::OpAssign));
102      }
103    }};}
104
105#[macro_export]
106macro_rules! impl_op_assign_range_fxn_v {
107  ($struct_name:ident, $op:ident, $ix:ty) => {
108    #[cfg(feature = "matrix")]
109    #[derive(Debug)]
110    pub struct $struct_name<T, MatA, MatB, IxVec> {
111      pub source: Ref<MatB>,
112      pub ixes: Ref<IxVec>,
113      pub sink: Ref<MatA>,
114      pub _marker: PhantomData<T>,
115    }
116    impl<T, R1: 'static, C1: 'static, S1: 'static, R2: 'static, C2: 'static, S2: 'static, IxVec: 'static> MechFunctionFactory for $struct_name<T, naMatrix<T, R1, C1, S1>, naMatrix<T, R2, C2, S2>, IxVec>
117    where
118      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
119      Ref<naMatrix<T, R2, C2, S2>>: ToValue,
120      T: Copy + Debug + Clone + Sync + Send + 'static +
121        Div<Output = T> + DivAssign +
122        Add<Output = T> + AddAssign +
123        Sub<Output = T> + SubAssign +
124        Mul<Output = T> + MulAssign +
125        Zero + One +
126        PartialEq + PartialOrd +
127        CompileConst + ConstElem + AsValueKind,
128      IxVec: CompileConst + ConstElem + AsNaKind + Debug + AsRef<[$ix]>,
129      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
130      R2: Dim, C2: Dim, S2: Storage<T, R2, C2> + Clone + Debug,
131      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + Debug + AsNaKind,
132      naMatrix<T, R2, C2, S2>: CompileConst + ConstElem + Debug + AsNaKind,
133    {
134      fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
135        match args {
136          FunctionArgs::Binary(out, arg1, arg2) => {
137            let source: Ref<naMatrix<T, R2, C2, S2>> = unsafe { arg1.as_unchecked() }.clone();
138            let ixes: Ref<IxVec> = unsafe { arg2.as_unchecked() }.clone();
139            let sink: Ref<naMatrix<T, R1, C1, S1>> = unsafe { out.as_unchecked() }.clone();
140            Ok(Box::new(Self { sink, source, ixes, _marker: PhantomData::default() }))
141          },
142          _ => Err(MechError{file: file!().to_string(), tokens: vec![], msg: format!("{} requires 3 arguments, got {:?}", stringify!($struct_name), args), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments})
143        }
144      }
145    }
146    impl<T, R1, C1, S1, R2, C2, S2, IxVec>
147      MechFunctionImpl for $struct_name<T, naMatrix<T, R1, C1, S1>, naMatrix<T, R2, C2, S2>, IxVec>
148    where
149      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
150      T: Copy + Debug + Clone + Sync + Send + 'static +
151        Div<Output = T> + DivAssign +
152        Add<Output = T> + AddAssign +
153        Sub<Output = T> + SubAssign +
154        Mul<Output = T> + MulAssign +
155        Zero + One +
156        PartialEq + PartialOrd,
157      IxVec: AsRef<[$ix]> + Debug,
158      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
159      R2: Dim, C2: Dim, S2: Storage<T, R2, C2> + Clone + Debug,
160    {
161      fn solve(&self) {
162        unsafe {
163          let sink_ptr = &mut *self.sink.as_mut_ptr();
164          let source_ptr = &*self.source.as_ptr();
165          let ix_ptr = &(*self.ixes.as_ptr()).as_ref();
166          $op!(source_ptr,ix_ptr,sink_ptr);
167        }
168      }
169      fn out(&self) -> Value {self.sink.to_value()}
170      fn to_string(&self) -> String {format!("{:#?}", self)}
171    }
172    #[cfg(feature = "compiler")]
173    impl<T, R1, C1, S1, R2, C2, S2, IxVec> MechFunctionCompiler for $struct_name<T, naMatrix<T, R1, C1, S1>, naMatrix<T, R2, C2, S2>, IxVec> 
174    where
175      T: CompileConst + ConstElem + AsValueKind,
176      IxVec: CompileConst + ConstElem + AsNaKind,
177      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
178      naMatrix<T, R2, C2, S2>: CompileConst + ConstElem + AsNaKind,
179    {
180      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
181        let name = format!("{}<{}{}{}{}>", stringify!($struct_name), T::as_value_kind(), naMatrix::<T, R1, C1, S1>::as_na_kind(), naMatrix::<T, R2, C2, S2>::as_na_kind(), IxVec::as_na_kind());
182        compile_binop!(name, self.sink, self.source, self.ixes, ctx, FeatureFlag::Builtin(FeatureKind::OpAssign));
183      }
184    }  
185  };}
186
187//impl_set_range_arms
188#[macro_export]
189macro_rules! op_assign_range_fxn {
190  ($op_fxn_name:tt, $fxn_name:ident) => {
191    paste::paste! {
192      fn $op_fxn_name(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
193        let arg = (sink, ixes.as_slice(), source);
194                     impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, u8, "u8")
195        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, u16, "u16"))
196        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, u32, "u32"))
197        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, u64, "u64"))
198        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, u128, "u128"))
199        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, i8, "i8"))
200        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, i16, "i16"))
201        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, i32, "i32"))
202        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, i64, "i64"))
203        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, F32, "f32"))
204        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, F64, "f64"))
205        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, R64, "rational"))
206        .or_else(|_| impl_assign_fxn!(impl_set_range_arms, $fxn_name, arg, C64, "complex"))
207        .map_err(|_| MechError { file: file!().to_string(), tokens: vec![], msg: format!("Unsupported argument: {:?}", &arg), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind})
208      }
209    }
210  }
211}
212
213#[macro_export]
214macro_rules! op_assign_range_all_fxn {
215  ($op_fxn_name:tt, $fxn_name:ident) => {
216    paste::paste! {
217      fn $op_fxn_name(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
218        let arg = (sink, ixes.as_slice(), source);
219                     impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, u8, "u8")
220        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, u16, "u16"))
221        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, u32, "u32"))
222        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, u64, "u64"))
223        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, u128, "u128"))
224        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, i8, "i8"))
225        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, i16, "i16"))
226        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, i32, "i32"))
227        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, i64, "i64"))
228        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, F32, "f32"))
229        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, F64, "f64"))
230        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, R64, "rational"))
231        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, C64, "complex"))
232        .map_err(|_| MechError { file: file!().to_string(), tokens: vec![], msg: format!("Unsupported argument: {:?}", &arg), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind})
233      }
234    }
235  }
236}
237
238#[macro_export]
239macro_rules! impl_assign_scalar_scalar {
240  ($op_name:tt, $op_fn:tt) => {
241    paste::paste! {
242      #[derive(Debug)]
243      struct [<$op_name AssignSS>]<T> {
244        sink: Ref<T>,
245        source: Ref<T>,
246      }
247      impl<T> MechFunctionFactory for [<$op_name AssignSS>]<T>
248      where
249        T: Debug + Clone + Sync + Send + 'static +
250           $op_name<Output = T> + [<$op_name Assign>] +
251           PartialEq + PartialOrd + CompileConst + ConstElem + AsValueKind,
252        Ref<T>: ToValue
253      {
254        fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
255          match args {
256            FunctionArgs::Unary(out, arg1) => {
257              let source: Ref<T> = unsafe { arg1.as_unchecked() }.clone();
258              let sink: Ref<T> = unsafe { out.as_unchecked() }.clone();
259              Ok(Box::new(Self { sink, source }))
260            },
261            _ => Err(MechError{file: file!().to_string(), tokens: vec![], msg: format!("{} requires 2 arguments, got {:?}", stringify!($struct_name), args), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments})
262          }    
263        }    
264      }
265      impl<T> MechFunctionImpl for [<$op_name AssignSS>]<T>
266      where
267        T: Debug + Clone + Sync + Send + 'static +
268           $op_name<Output = T> + [<$op_name Assign>] +
269           PartialEq + PartialOrd,
270        Ref<T>: ToValue
271      {
272        fn solve(&self) {
273          let sink_ptr = self.sink.as_mut_ptr();
274          let source_ptr = self.source.as_ptr();
275          unsafe {
276            *sink_ptr $op_fn (*source_ptr).clone();
277          }
278        }
279        fn out(&self) -> Value { self.sink.to_value() }
280        fn to_string(&self) -> String { format!("{:#?}", self) }
281      }
282      #[cfg(feature = "compiler")]
283      impl<T> MechFunctionCompiler for [<$op_name AssignSS>]<T> 
284      where
285        T: CompileConst + ConstElem + AsValueKind,
286      {
287        fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
288          let name = format!("{}AssignSS<{}>", stringify!($op_name), T::as_value_kind());
289          compile_unop!(name, self.sink, self.source, ctx, FeatureFlag::Builtin(FeatureKind::Assign) );
290        }
291      }
292      register_fxn_descriptor!([<$op_name AssignSS>], 
293        u8, "u8", 
294        u16, "u16",
295        u32, "u32",
296        u64, "u64",
297        u128, "u128",
298        i8, "i8",
299        i16, "i16",
300        i32, "i32",
301        i64, "i64",
302        i128, "i128",
303        F32, "f32",
304        F64, "f64",
305        R64, "r64",
306        C64, "c64"
307      );
308    }
309  };
310}
311
312#[macro_export]
313macro_rules! impl_assign_vector_vector {
314  ($op_name:tt, $op_fn:tt) => {
315    paste::paste! {
316      #[derive(Debug)]
317      pub struct [<$op_name AssignVV>]<T, MatA, MatB> {
318        pub sink: Ref<MatA>,
319        pub source: Ref<MatB>,
320        _marker: PhantomData<T>,
321      }
322      impl<T, MatA, MatB> MechFunctionFactory for [<$op_name AssignVV>]<T, MatA, MatB>
323      where
324        Ref<MatA>: ToValue,
325        T: Debug + Clone + Sync + Send + 'static + [<$op_name Assign>] +
326        CompileConst + ConstElem + AsValueKind,
327        for<'a> &'a MatA: IntoIterator<Item = &'a T>,
328        for<'a> &'a mut MatA: IntoIterator<Item = &'a mut T>,
329        for<'a> &'a MatB: IntoIterator<Item = &'a T>,
330        MatA: Debug + CompileConst + ConstElem + AsValueKind + 'static,
331        MatB: Debug + CompileConst + ConstElem + AsValueKind + 'static,
332      {
333        fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
334          match args {
335            FunctionArgs::Unary(out, arg1) => {
336              let source: Ref<MatB> = unsafe { arg1.as_unchecked() }.clone();
337              let sink: Ref<MatA> = unsafe { out.as_unchecked() }.clone();
338              Ok(Box::new(Self { sink, source, _marker: PhantomData::default() }))
339            },
340            _ => Err(MechError{file: file!().to_string(), tokens: vec![], msg: format!("{} requires 2 arguments, got {:?}", stringify!($struct_name), args), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments})
341          }    
342        }    
343      }
344      impl<T, MatA, MatB> MechFunctionImpl for [<$op_name AssignVV>]<T, MatA, MatB>
345      where
346        Ref<MatA>: ToValue,
347        T: Debug + Clone + Sync + Send + 'static + [<$op_name Assign>],
348        for<'a> &'a MatA: IntoIterator<Item = &'a T>,
349        for<'a> &'a mut MatA: IntoIterator<Item = &'a mut T>,
350        for<'a> &'a MatB: IntoIterator<Item = &'a T>,
351        MatA: Debug,
352        MatB: Debug,
353      {
354        fn solve(&self) {
355          unsafe {
356            let sink_ptr = self.sink.as_mut_ptr();
357            let source_ptr = self.source.as_ptr();
358            let sink_ref: &mut MatA = &mut *sink_ptr;
359            let source_ref: &MatB = &*source_ptr;
360            for (dst, src) in (&mut *sink_ref).into_iter().zip((&*source_ref).into_iter()) {
361              *dst $op_fn src.clone();
362            }
363          }
364        }
365        fn out(&self) -> Value {self.sink.to_value()}
366        fn to_string(&self) -> String {format!("{:#?}", self)}
367      }
368      #[cfg(feature = "compiler")]
369      impl<T, MatA, MatB> MechFunctionCompiler for [<$op_name AssignVV>]<T, MatA, MatB> 
370      where
371        T: CompileConst + ConstElem + AsValueKind,
372        MatA: CompileConst + ConstElem + AsValueKind,
373        MatB: CompileConst + ConstElem + AsValueKind,
374      {
375        fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
376          let name = format!("{}AssignVV<{}>", stringify!($op_name), MatA::as_value_kind());
377          compile_unop!(name, self.sink, self.source, ctx, FeatureFlag::Builtin(FeatureKind::OpAssign) );
378        }
379      }
380      impl_register_op_assign_vv_all!([<$op_name AssignVV>]);
381    }
382  };
383}
384
385#[macro_export]
386macro_rules! impl_assign_vector_scalar {
387  ($op_name:tt, $op_fn:tt) => {
388    paste::paste! {
389      #[derive(Debug)]
390      pub struct [<$op_name AssignVS>]<T, MatA> {
391        pub sink: Ref<MatA>,
392        pub source: Ref<T>,
393        _marker: PhantomData<T>,
394      }
395      impl<T, MatA> MechFunctionFactory for [<$op_name AssignVS>]<T, MatA>
396      where
397        Ref<MatA>: ToValue,
398        T: Debug + Clone + Sync + Send + 'static + [<$op_name Assign>] +
399        CompileConst + ConstElem + AsValueKind,
400        for<'a> &'a MatA: IntoIterator<Item = &'a T>,
401        for<'a> &'a mut MatA: IntoIterator<Item = &'a mut T>,
402        MatA: Debug + CompileConst + ConstElem + AsValueKind + 'static,
403      {
404        fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
405          match args {
406            FunctionArgs::Binary(out, arg1, arg2) => {
407              let source: Ref<T> = unsafe { arg2.as_unchecked() }.clone();
408              let sink: Ref<MatA> = unsafe { out.as_unchecked() }.clone();
409              Ok(Box::new(Self { sink, source, _marker: PhantomData::default() }))
410            },
411            _ => Err(MechError{file: file!().to_string(), tokens: vec![], msg: format!("{} requires 2 arguments, got {:?}", stringify!($struct_name), args), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments})
412          }    
413        }    
414      }
415      impl<T, MatA> MechFunctionImpl for [<$op_name AssignVS>]<T, MatA>
416      where
417        Ref<MatA>: ToValue,
418        T: Debug + Clone + Sync + Send + 'static + [<$op_name Assign>],
419        for<'a> &'a MatA: IntoIterator<Item = &'a T>,
420        for<'a> &'a mut MatA: IntoIterator<Item = &'a mut T>,
421        MatA: Debug,
422      {
423        fn solve(&self) {
424          unsafe {
425            let sink_ptr = self.sink.as_mut_ptr();
426            let source_ptr = self.source.as_ptr();
427            let sink_ref: &mut MatA = &mut *sink_ptr;
428            let source_ref: &T = &*source_ptr;
429            for dst in (&mut *sink_ref).into_iter() {
430              *dst $op_fn source_ref.clone();
431            }
432          }
433        }
434        fn out(&self) -> Value {self.sink.to_value()}
435        fn to_string(&self) -> String {format!("{:#?}", self)}
436      }
437      #[cfg(feature = "compiler")]
438      impl<T, MatA> MechFunctionCompiler for [<$op_name AssignVS>]<T, MatA> 
439      where
440        T: CompileConst + ConstElem + AsValueKind,
441        MatA: CompileConst + ConstElem + AsValueKind,
442      {
443        fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
444          let name = format!("{}AssignVS<{}>", stringify!($op_name), MatA::as_value_kind());
445          compile_unop!(name, self.sink, self.source, ctx, FeatureFlag::Builtin(FeatureKind::OpAssign) );
446        }
447      }
448    }
449  }
450}
451
452#[macro_export]
453macro_rules! register_op_assign_vv {
454  ($op:ident, $type:ty, $size:ty, $size_string:tt) => {
455    paste!{
456      register_descriptor! {
457        FunctionDescriptor {
458          name: concat!(stringify!($op),"<[",stringify!([<$type:lower>]),"]:", $size_string, ">"),
459          ptr: $op::<$type,$size<$type>,$size<$type>>::new,
460        }
461      }
462    }
463  };}
464
465#[macro_export]
466macro_rules! register_op_assign_vv_all {
467  ($op:ident, $ty:ty, $ty_feature:literal) => {
468    #[cfg(feature = "row_vector4")]
469    register_op_assign_vv!($op, $ty, RowVector4, "1,4");
470    #[cfg(feature = "row_vector3")]
471    register_op_assign_vv!($op, $ty, RowVector3, "1,3");
472    #[cfg(feature = "row_vector2")]
473    register_op_assign_vv!($op, $ty, RowVector2, "1,2");
474    #[cfg(feature = "vector2")]
475    register_op_assign_vv!($op, $ty, Vector2, "2,1");
476    #[cfg(feature = "vector3")]
477    register_op_assign_vv!($op, $ty, Vector3, "3,1");
478    #[cfg(feature = "vector4")]
479    register_op_assign_vv!($op, $ty, Vector4, "4,1");
480    #[cfg(feature = "matrix1")]
481    register_op_assign_vv!($op, $ty, Matrix1, "1,1");
482    #[cfg(feature = "matrix2")]
483    register_op_assign_vv!($op, $ty, Matrix2, "2,2");
484    #[cfg(feature = "matrix3")]
485    register_op_assign_vv!($op, $ty, Matrix3, "3,3");
486    #[cfg(feature = "matrix4")]
487    register_op_assign_vv!($op, $ty, Matrix4, "4,4");
488    #[cfg(feature = "matrix2x3")]
489    register_op_assign_vv!($op, $ty, Matrix2x3, "2,3");
490    #[cfg(feature = "matrix3x2")]
491    register_op_assign_vv!($op, $ty, Matrix3x2, "3,2");
492    #[cfg(feature = "vectord")]
493    register_op_assign_vv!($op, $ty, DVector, "0,1");
494    #[cfg(feature = "matrixd")]
495    register_op_assign_vv!($op, $ty, DMatrix, "0,0");
496    #[cfg(feature = "row_vectord")]
497    register_op_assign_vv!($op, $ty, RowDVector, "1,0");
498  };
499}
500
501#[macro_export]
502macro_rules! impl_register_op_assign_vv_all {
503  ($macro_name:ident) => {
504    #[cfg(feature = "u8")]
505    register_op_assign_vv_all!($macro_name, u8, "u8");
506    #[cfg(feature = "u16")]
507    register_op_assign_vv_all!($macro_name, u16, "u16");
508    #[cfg(feature = "u32")]
509    register_op_assign_vv_all!($macro_name, u32, "u32");
510    #[cfg(feature = "u64")]
511    register_op_assign_vv_all!($macro_name, u64, "u64");
512    #[cfg(feature = "u128")]
513    register_op_assign_vv_all!($macro_name, u128, "u128");
514    #[cfg(feature = "i8")]
515    register_op_assign_vv_all!($macro_name, i8, "i8");
516    #[cfg(feature = "i16")]
517    register_op_assign_vv_all!($macro_name, i16, "i16");
518    #[cfg(feature = "i32")]
519    register_op_assign_vv_all!($macro_name, i32, "i32");
520    #[cfg(feature = "i64")]
521    register_op_assign_vv_all!($macro_name, i64, "i64");
522    #[cfg(feature = "i128")]
523    register_op_assign_vv_all!($macro_name, i128, "i128");
524    #[cfg(feature = "f32")]
525    register_op_assign_vv_all!($macro_name, F32, "f32");
526    #[cfg(feature = "f64")]
527    register_op_assign_vv_all!($macro_name, F64, "f64");
528    #[cfg(feature = "r64")]
529    register_op_assign_vv_all!($macro_name, R64, "r64");
530    #[cfg(feature = "c64")]
531    register_op_assign_vv_all!($macro_name, C64, "c64");
532  };
533}
534
535#[macro_export]
536macro_rules! impl_op_assign_value_match_arms {
537  ($op:tt, $arg:expr,$($value_kind:ident, $feature:tt);+ $(;)?) => {
538    paste::paste! {
539      match $arg {
540        $(
541          #[cfg(feature = $feature)]
542          (Value::$value_kind(sink), Value::$value_kind(source)) => Ok(Box::new([<$op AssignSS>]{ sink: sink.clone(), source: source.clone() })),
543          #[cfg(all(feature = $feature, feature = "matrix1"))]
544          (Value::[<Matrix $value_kind>](Matrix::Matrix1(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
545          #[cfg(all(feature = $feature, feature = "matrix2"))]
546          (Value::[<Matrix $value_kind>](Matrix::Matrix2(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
547          #[cfg(all(feature = $feature, feature = "matrix2x3"))]
548          (Value::[<Matrix $value_kind>](Matrix::Matrix2x3(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
549          #[cfg(all(feature = $feature, feature = "matrix3x2"))]
550          (Value::[<Matrix $value_kind>](Matrix::Matrix3x2(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
551          #[cfg(all(feature = $feature, feature = "matrix3"))]
552          (Value::[<Matrix $value_kind>](Matrix::Matrix3(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
553          #[cfg(all(feature = $feature, feature = "matrix4"))]
554          (Value::[<Matrix $value_kind>](Matrix::Matrix4(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
555          #[cfg(all(feature = $feature, feature = "matrixd"))]
556          (Value::[<Matrix $value_kind>](Matrix::DMatrix(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
557          #[cfg(all(feature = $feature, feature = "vector2"))]
558          (Value::[<Matrix $value_kind>](Matrix::Vector2(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
559          #[cfg(all(feature = $feature, feature = "vector3"))]
560          (Value::[<Matrix $value_kind>](Matrix::Vector3(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
561          #[cfg(all(feature = $feature, feature = "vector4"))]
562          (Value::[<Matrix $value_kind>](Matrix::Vector4(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
563          #[cfg(all(feature = $feature, feature = "vectord"))]
564          (Value::[<Matrix $value_kind>](Matrix::DVector(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
565          #[cfg(all(feature = $feature, feature = "row_vector2"))]
566          (Value::[<Matrix $value_kind>](Matrix::RowVector2(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})), 
567          #[cfg(all(feature = $feature, feature = "row_vector3"))]
568          (Value::[<Matrix $value_kind>](Matrix::RowVector3(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})), 
569          #[cfg(all(feature = $feature, feature = "row_vector4"))]
570          (Value::[<Matrix $value_kind>](Matrix::RowVector4(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})), 
571          #[cfg(all(feature = $feature, feature = "row_vectord"))]
572          (Value::[<Matrix $value_kind>](Matrix::RowDVector(sink)), Value::$value_kind(source)) => Ok(Box::new([<$op AssignVS>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})), 
573          #[cfg(all(feature = $feature, feature = "matrix1"))]
574          (Value::[<Matrix $value_kind>](Matrix::Matrix1(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix1(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
575          #[cfg(all(feature = $feature, feature = "matrix2"))]
576          (Value::[<Matrix $value_kind>](Matrix::Matrix2(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix2(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
577          #[cfg(all(feature = $feature, feature = "matrix2x3"))]
578          (Value::[<Matrix $value_kind>](Matrix::Matrix2x3(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix2x3(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
579          #[cfg(all(feature = $feature, feature = "matrix3x2"))]
580          (Value::[<Matrix $value_kind>](Matrix::Matrix3x2(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix3x2(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
581          #[cfg(all(feature = $feature, feature = "matrix3"))]
582          (Value::[<Matrix $value_kind>](Matrix::Matrix3(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix3(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
583          #[cfg(all(feature = $feature, feature = "matrix4"))]
584          (Value::[<Matrix $value_kind>](Matrix::Matrix4(sink)), Value::[<Matrix $value_kind>](Matrix::Matrix4(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
585          #[cfg(all(feature = $feature, feature = "matrixd"))]
586          (Value::[<Matrix $value_kind>](Matrix::DMatrix(sink)), Value::[<Matrix $value_kind>](Matrix::DMatrix(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
587          #[cfg(all(feature = $feature, feature = "vector2"))]
588          (Value::[<Matrix $value_kind>](Matrix::Vector2(sink)), Value::[<Matrix $value_kind>](Matrix::Vector2(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
589          #[cfg(all(feature = $feature, feature = "vector3"))]
590          (Value::[<Matrix $value_kind>](Matrix::Vector3(sink)), Value::[<Matrix $value_kind>](Matrix::Vector3(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
591          #[cfg(all(feature = $feature, feature = "vector4"))]
592          (Value::[<Matrix $value_kind>](Matrix::Vector4(sink)), Value::[<Matrix $value_kind>](Matrix::Vector4(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
593          #[cfg(all(feature = $feature, feature = "vectord"))]
594          (Value::[<Matrix $value_kind>](Matrix::DVector(sink)), Value::[<Matrix $value_kind>](Matrix::DVector(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
595          #[cfg(all(feature = $feature, feature = "row_vector2"))]
596          (Value::[<Matrix $value_kind>](Matrix::RowVector2(sink)), Value::[<Matrix $value_kind>](Matrix::RowVector2(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
597          #[cfg(all(feature = $feature, feature = "row_vector3"))]
598          (Value::[<Matrix $value_kind>](Matrix::RowVector3(sink)), Value::[<Matrix $value_kind>](Matrix::RowVector3(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
599          #[cfg(all(feature = $feature, feature = "row_vector4"))]
600          (Value::[<Matrix $value_kind>](Matrix::RowVector4(sink)), Value::[<Matrix $value_kind>](Matrix::RowVector4(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
601          #[cfg(all(feature = $feature, feature = "row_vectord"))]
602          (Value::[<Matrix $value_kind>](Matrix::RowDVector(sink)), Value::[<Matrix $value_kind>](Matrix::RowDVector(source))) => Ok(Box::new([<$op AssignVV>]{sink: sink.clone(), source: source.clone(), _marker: PhantomData::default()})),
603        )+
604        x => Err(MechError {file: file!().to_string(),tokens: vec![],msg: format!("Unhandled args {:?}", x),id: line!(),kind: MechErrorKind::UnhandledFunctionArgumentKind,}),
605      }
606    }
607  };
608}