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