mech_interpreter/stdlib/assign/
matrix.rs

1#[macro_use]
2use crate::stdlib::*;
3use std::marker::PhantomData;
4use std::fmt::Debug;
5use nalgebra::{
6  IsContiguous,
7  base::{Matrix as naMatrix, Storage, StorageMut},
8  Dim, Scalar,
9};
10
11// Assign -----------------------------------------------------------------
12
13#[macro_export]
14macro_rules! impl_set_match_arms {
15  ($fxn_name:ident,$macro_name:ident, $arg:expr) => {
16    paste!{
17      [<impl_set_ $macro_name _match_arms>]!(
18        $fxn_name,
19        $arg,
20        Bool, "bool";
21        U8, "u8";
22        U16, "u16";
23        U32, "u32";
24        U64, "u64";
25        U128, "u128";
26        I8, "i8";
27        I16, "i16";
28        I32, "i32";
29        I64, "i64";
30        U128, "u128";
31        F32, "f32"; 
32        F64, "f64" ;
33        String, "string";
34        C64, "complex";
35        R64, "rational";
36      )
37    }
38  }
39}
40
41#[macro_export]
42macro_rules! impl_set_all_fxn_s {
43  ($struct_name:ident, $op:ident, $ix:ty) => {
44    #[derive(Debug)]
45    pub struct $struct_name<T, MatA, IxVec> {
46      pub source: Ref<T>,
47      pub ixes: Ref<IxVec>,
48      pub sink: Ref<MatA>,
49      pub _marker: PhantomData<T>,
50    }
51    impl<T, R1, C1, S1: 'static, IxVec: 'static> MechFunctionFactory for $struct_name<T, naMatrix<T, R1, C1, S1>, IxVec>
52    where
53      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
54      T: Scalar + Clone + Debug + Sync + Send + 'static + CompileConst + ConstElem + AsValueKind,
55      IxVec: CompileConst + ConstElem + Debug + AsRef<[$ix]> + AsNaKind,
56      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
57      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + Debug + AsNaKind,
58    {
59      fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
60        match args {
61          FunctionArgs::Binary(out, arg1, arg2) => {
62            let source: Ref<T> = unsafe { arg1.as_unchecked() }.clone();
63            let ixes: Ref<IxVec> = unsafe { arg2.as_unchecked() }.clone();
64            let sink: Ref<naMatrix<T, R1, C1, S1>> = unsafe { out.as_unchecked() }.clone();
65            Ok(Box::new(Self { sink, source, ixes, _marker: PhantomData::default() }))
66          },
67          _ => Err(MechError2::new(
68              IncorrectNumberOfArguments { expected: 2, found: args.len() },
69              None
70            ).with_compiler_loc()
71          ),
72        }
73      }
74    }
75    impl<T, R1, C1, S1, IxVec> MechFunctionImpl for $struct_name<T, naMatrix<T, R1, C1, S1>, IxVec>
76    where
77      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
78      T: Scalar + Clone + Debug + Sync + Send + 'static,
79      IxVec: AsRef<[$ix]> + Debug,
80      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
81    {
82      fn solve(&self) {
83        unsafe {
84          let sink_ptr = &mut *self.sink.as_mut_ptr();
85          let source_ptr = &*self.source.as_ptr();
86          let ix_ptr = &(*self.ixes.as_ptr()).as_ref();
87          $op!(source_ptr,ix_ptr,sink_ptr);
88        }
89      }
90      fn out(&self) -> Value {self.sink.to_value()}
91      fn to_string(&self) -> String {format!("{:#?}", self)}
92    }
93    #[cfg(feature = "compiler")]
94    impl<T, R1, C1, S1, IxVec> MechFunctionCompiler for $struct_name<T, naMatrix<T, R1, C1, S1>, IxVec> 
95    where
96      T: CompileConst + ConstElem + AsValueKind,
97      IxVec: CompileConst + ConstElem + AsNaKind,
98      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
99    {
100      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
101        let name = format!("{}<{}{}{}>", stringify!($struct_name), T::as_value_kind(), naMatrix::<T, R1, C1, S1>::as_na_kind(), IxVec::as_na_kind());
102        compile_binop!(name, self.sink, self.ixes, self.source, ctx, FeatureFlag::Builtin(FeatureKind::Assign));
103      }
104    }};}
105
106// x[1] = 1 ------------------------------------------------------------------
107
108#[macro_export]
109macro_rules! assign_1d_scalar {
110  ($source:expr, $ix:expr, $sink:expr) => {
111      ($sink)[$ix - 1] = ($source).clone();
112    };}
113
114#[macro_export]
115macro_rules! assign_1d_scalar_b {
116  ($source:expr, $ix:expr, $sink:expr) => {
117    if $ix {
118      for ix in 0..$sink.len() {
119        $sink[ix] = $source.clone();
120      }
121    }
122  };}
123
124#[macro_export]
125macro_rules! assign_1d_scalar_vb {
126  ($source:expr, $ix:expr, $sink:expr) => {
127    if *$ix {
128      let len = $sink.len().min($source.len());
129      for ix in 0..len {
130        $sink[ix] = $source[ix].clone();
131      }
132    }
133  };}
134
135#[macro_export]
136macro_rules! impl_assign_fxn_s {
137  ($struct_name:ident, $op:ident, $ix:ty) => {
138    #[derive(Debug)]
139    pub struct $struct_name<T, MatA> {
140      pub source: Ref<T>,
141      pub ixes: Ref<$ix>,
142      pub sink: Ref<MatA>,
143      pub _marker: PhantomData<T>,
144    }
145    impl<T, R, C, S: 'static> MechFunctionFactory for $struct_name<T, naMatrix<T, R, C, S>>
146    where
147      Ref<naMatrix<T, R, C, S>>: ToValue,
148      T: Scalar + Clone + Debug + Sync + Send + 'static +
149        CompileConst + ConstElem + AsValueKind,
150      R: Dim, C: Dim, S: StorageMut<T, R, C> + Clone + Debug,
151      naMatrix<T, R, C, S>: CompileConst + ConstElem + AsNaKind,
152    {
153      fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
154        match args {
155          FunctionArgs::Binary(out, arg1, arg2) => {
156            let source: Ref<T> = unsafe { arg1.as_unchecked() }.clone();
157            let ixes: Ref<$ix> = unsafe { arg2.as_unchecked() }.clone();
158            let sink: Ref<naMatrix<T, R, C, S>> = unsafe { out.as_unchecked() }.clone();
159            Ok(Box::new(Self { sink, source, ixes, _marker: PhantomData::default() }))
160          },
161          _ => Err(MechError2::new(
162              IncorrectNumberOfArguments { expected: 2, found: args.len() },
163              None
164            ).with_compiler_loc()
165          ),
166        }
167      }
168    }
169    impl<T, R, C, S> MechFunctionImpl for $struct_name<T, naMatrix<T, R, C, S>>
170    where
171      Ref<naMatrix<T, R, C, S>>: ToValue,
172      T: Scalar + Clone + Debug + Sync + Send + 'static,
173      R: Dim,
174      C: Dim,
175      S: StorageMut<T, R, C> + Clone + Debug,
176    {
177      fn solve(&self) {
178        unsafe {
179          let mut sink_ptr = &mut *self.sink.as_mut_ptr();
180          let ix_val = (*self.ixes.as_ptr()).clone();
181          let source_val = (*self.source.as_ptr()).clone();
182          $op!(source_val, ix_val, sink_ptr);
183        }
184      }
185      fn out(&self) -> Value {self.sink.to_value()}
186      fn to_string(&self) -> String {format!("{:#?}", self)}
187    }
188    #[cfg(feature = "compiler")]
189    impl<T, R, C, S> MechFunctionCompiler for $struct_name<T, naMatrix<T, R, C, S>> 
190    where
191      T: CompileConst + ConstElem + AsValueKind,
192      naMatrix<T, R, C, S>: CompileConst + ConstElem + AsNaKind,
193    {
194      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
195        let name = format!("{}<{}{}>", stringify!($struct_name), T::as_value_kind(), naMatrix::<T, R, C, S>::as_na_kind());
196        compile_binop!(name, self.sink, self.ixes, self.source, ctx, FeatureFlag::Builtin(FeatureKind::Assign));
197      }
198    }};}
199
200impl_assign_fxn_s!(Assign1DS, assign_1d_scalar, usize);
201impl_assign_fxn_s!(Assign1DB, assign_1d_scalar_b, bool);
202impl_assign_scalar_fxn_v!(Assign1DVB, assign_1d_scalar_vb, bool);
203
204fn impl_assign_scalar_fxn(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
205  let arg = (sink.clone(), ixes.as_slice(), source.clone());
206               impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, u8,   "u8")
207  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, u16,  "u16"))
208  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, u32,  "u32"))
209  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, u64,  "u64"))
210  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, u128, "u128"))
211  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, i8,   "i8"))
212  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, i16,  "i16"))
213  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, i32,  "i32"))
214  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, i64,  "i64"))
215  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, i128, "i128"))
216  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, f32,  "f32"))
217  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, f64,  "f64"))
218  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, R64,  "rational"))
219  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, C64,  "complex"))
220  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, bool, "bool"))
221  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms,  Assign1D, arg, String, "string"))
222
223  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, u8,  "u8"))
224  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, u16,  "u16"))
225  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, u32,  "u32"))
226  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, u64,  "u64"))
227  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, u128, "u128"))
228  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, i8,   "i8"))
229  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, i16,  "i16"))
230  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, i32,  "i32"))
231  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, i64,  "i64"))
232  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, i128, "i128"))
233  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, f32,  "f32"))
234  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, f64,  "f64"))
235  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, R64,  "rational"))
236  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, C64,  "complex"))
237  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, bool, "bool"))
238  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_arms_b,  Assign1D, arg, String, "string"))
239  .map_err(|_| MechError2::new(
240      UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "matrix/assign-scalar".to_string() },
241      None
242    ).with_compiler_loc()
243  )
244}
245
246pub struct MatrixAssignScalar {}
247impl NativeFunctionCompiler for MatrixAssignScalar {
248  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
249    if arguments.len() <= 1 {
250      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
251    }
252    let sink: Value = arguments[0].clone();
253    let source: Value = arguments[1].clone();
254    let ixes = arguments.clone().split_off(2);
255    match impl_assign_scalar_fxn(sink.clone(),source.clone(),ixes.clone()) {
256      Ok(fxn) => Ok(fxn),
257      Err(x) => {
258        match sink {
259          Value::MutableReference(sink) => { impl_assign_scalar_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) }
260          sink => Err(MechError2::new(
261              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "matrix/assign-scalar".to_string() },
262              None
263            ).with_compiler_loc()
264          ),
265        }
266      }
267    }
268  }
269}
270
271// x[1..3] = 1 ----------------------------------------------------------------
272
273macro_rules! set_1d_range {
274  ($source:expr, $ix:expr, $sink:expr) => {
275    unsafe { 
276      for i in 0..($ix).len() {
277        ($sink)[($ix)[i] - 1] = ($source).clone();
278      }
279    }
280  };}
281
282macro_rules! set_1d_range_b {
283  ($source:expr, $ix:expr, $sink:expr) => {
284    unsafe { 
285      for i in 0..($ix).len() {
286        if $ix[i] == true {
287          ($sink)[i] = ($source).clone();
288        }
289      }
290    }
291  };}  
292
293macro_rules! set_1d_range_vec {
294  ($source:expr, $ix:expr, $sink:expr) => {
295    unsafe { 
296      for i in 0..($ix).len() {
297        ($sink)[($ix)[i] - 1] = ($source)[i].clone();
298      }
299    }
300  };}  
301
302macro_rules! set_1d_range_vec_b {
303  ($source:expr, $ix:expr, $sink:expr) => {
304    unsafe {
305      for i in 0..($ix).len() {
306        if $ix[i] == true {
307          ($sink)[i] = ($source)[i].clone();
308        }
309      }
310    }};}
311
312impl_set_all_fxn_s!(Assign1DRS,set_1d_range,usize);
313impl_set_all_fxn_s!(Assign1DRB,set_1d_range_b,bool);
314impl_all_fxn_v!(Assign1DRV,set_1d_range_vec,usize);
315impl_all_fxn_v!(Assign1DRVB,set_1d_range_vec_b,bool);
316
317fn impl_assign_range_fxn(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
318  let arg = (sink.clone(), ixes.as_slice(), source.clone());
319                impl_assign_fxn!(impl_set_range_arms, Assign1DR, arg, u8,   "u8")
320  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, u16,  "u16"))
321  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, u32,  "u32"))
322  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, u64,  "u64"))
323  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, u128, "u128"))
324  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, i8,   "i8"))
325  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, i16,  "i16"))
326  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, i32,  "i32"))
327  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, i64,  "i64"))
328  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, i128, "i128"))
329  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, f32,  "f32"))
330  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, f64,  "f64"))
331  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, R64,  "rational"))
332  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, C64,  "complex"))
333  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, bool, "bool"))
334  .or_else(|_| impl_assign_fxn!(impl_set_range_arms,  Assign1DR, arg, String, "string"))
335
336  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, u8,  "u8"))
337  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, u16,  "u16"))
338  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, u32,  "u32"))
339  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, u64,  "u64"))
340  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, u128, "u128"))
341  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, i8,   "i8"))
342  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, i16,  "i16"))
343  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, i32,  "i32"))
344  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, i64,  "i64"))
345  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, i128, "i128"))
346  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, f32,  "f32"))
347  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, f64,  "f64"))
348  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, R64,  "rational"))
349  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, C64,  "complex"))
350  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, bool, "bool"))
351  .or_else(|_| impl_set_range_arms_b!(Assign1DR, &arg, String, "string"))
352  .map_err(|_| MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignRange".to_string() }, None).with_compiler_loc())
353}
354
355pub struct MatrixAssignRange {}
356impl NativeFunctionCompiler for MatrixAssignRange {
357  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
358    if arguments.len() <= 1 {
359      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
360    }
361    let sink: Value = arguments[0].clone();
362    let source: Value = arguments[1].clone();
363    let ixes = arguments.clone().split_off(2);
364    match impl_assign_range_fxn(sink.clone(),source.clone(),ixes.clone()) {
365      Ok(fxn) => Ok(fxn),
366      Err(x) => {
367        match (sink.clone(),&ixes,source.clone()) {
368          (Value::MutableReference(sink),_,Value::MutableReference(source)) => { impl_assign_range_fxn(sink.borrow().clone(),source.borrow().clone(),ixes.clone()) },
369          (sink,_,Value::MutableReference(source)) => { impl_assign_range_fxn(sink.clone(),source.borrow().clone(),ixes.clone()) },
370          (Value::MutableReference(sink),_,source) => { impl_assign_range_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) },
371          (sink, ixes, source) => Err(MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignRange".to_string() }, None).with_compiler_loc()),
372        }
373      }
374    }
375  }
376}
377
378// x[:] = 1 ------------------------------------------------------------------
379
380#[derive(Debug)]
381pub struct Set1DAS<T, Sink> {
382  pub source: Ref<T>,
383  pub sink: Ref<Sink>,
384  pub _marker: PhantomData<T>,
385}
386impl<T, R, C, S> MechFunctionFactory for Set1DAS<T, naMatrix<T, R, C, S>>
387where
388  Ref<naMatrix<T, R, C, S>>: ToValue,
389  T: Debug + Clone + Sync + Send + PartialEq + 'static +
390    CompileConst + ConstElem + AsValueKind,
391  R: Dim,
392  C: Dim,
393  S: StorageMut<T, R, C> + Debug + IsContiguous + 'static,
394  naMatrix<T, R, C, S>: CompileConst + ConstElem + Debug + AsNaKind,
395{
396  fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
397    match args {
398      FunctionArgs::Unary(out, arg1) => {
399        let source: Ref<T> = unsafe { arg1.as_unchecked() }.clone();
400        let sink: Ref<naMatrix<T, R, C, S>> = unsafe { out.as_unchecked() }.clone();
401        Ok(Box::new(Self { sink, source, _marker: PhantomData::default() }))
402      },
403      _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: args.len() }, None).with_compiler_loc())
404    }
405  }
406}
407impl<T, R, C, S> MechFunctionImpl for Set1DAS<T, naMatrix<T, R, C, S>>
408where
409  T: Debug + Clone + Sync + Send + PartialEq + 'static,
410  R: Dim,
411  C: Dim,
412  S: StorageMut<T, R, C> + Debug + IsContiguous,
413  Ref<naMatrix<T, R, C, S>>: ToValue,
414{
415  fn solve(&self) {
416    unsafe {
417      let sink = &mut *self.sink.as_mut_ptr();
418      let source_val = (*self.source.as_ptr()).clone();
419      let slice = sink.as_mut_slice();
420      for elem in slice.iter_mut() {
421        *elem = source_val.clone();
422      }
423    }
424  }
425  fn out(&self) -> Value {self.sink.to_value()}
426  fn to_string(&self) -> String {format!("{:#?}", self)}
427}
428#[cfg(feature = "compiler")]
429impl<T, R, C, S> MechFunctionCompiler for Set1DAS<T, naMatrix<T, R, C, S>> 
430where
431  T: CompileConst + ConstElem + AsValueKind,
432  naMatrix<T, R, C, S>: CompileConst + ConstElem + AsNaKind,
433{ 
434  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
435    let name = format!("Set1DAS<{}{}>", T::as_value_kind(), naMatrix::<T, R, C, S>::as_na_kind());
436    compile_unop!(name, self.sink, self.source, ctx, FeatureFlag::Builtin(FeatureKind::Assign));
437  }
438}
439
440fn impl_assign_all_fxn(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
441  let arg = (sink.clone(), ixes.as_slice(), source.clone());
442               impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, u8,   "u8")
443  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, u16,  "u16"))
444  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, u32,  "u32"))
445  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, u64,  "u64"))
446  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, u128, "u128"))
447  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, i8,   "i8"))
448  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, i16,  "i16"))
449  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, i32,  "i32"))
450  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, i64,  "i64"))
451  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, i128, "i128"))
452  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, f32,  "f32"))
453  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, f64,  "f64"))
454  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, R64,  "rational"))
455  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, C64,  "complex"))
456  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, bool, "bool"))
457  .or_else(|_| impl_assign_fxn!(impl_assign_all_arms, Set1DA, arg, String, "string"))
458  .map_err(|_| MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignAll".to_string() }, None).with_compiler_loc())
459}
460
461pub struct MatrixAssignAll {}
462impl NativeFunctionCompiler for MatrixAssignAll {
463  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
464    if arguments.len() <= 1 {
465      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
466    }
467    let sink: Value = arguments[0].clone();
468    let source: Value = arguments[1].clone();
469    let ixes = arguments.clone().split_off(2);
470    match impl_assign_all_fxn(sink.clone(),source.clone(),ixes.clone()) {
471      Ok(fxn) => Ok(fxn),
472      Err(_) => {
473        match sink {
474          Value::MutableReference(sink) => { impl_assign_all_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) }
475          _ => Err(MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignAll".to_string() }, None).with_compiler_loc()),
476        }
477      }
478    }
479  }
480}
481
482// x[1,1] = 1 ----------------------------------------------------------------
483
484#[derive(Debug)]
485pub struct Assign2DSSS<T, MatA> {
486  pub source: Ref<T>,
487  pub ixes: (Ref<usize>, Ref<usize>),
488  pub sink: Ref<MatA>,
489  pub _marker: PhantomData<T>,
490}
491impl<T, R1, C1, S1: 'static> MechFunctionFactory for Assign2DSSS<T, naMatrix<T, R1, C1, S1>>
492where
493  Ref<naMatrix<T, R1, C1, S1>>: ToValue,
494  T: Scalar + Clone + Debug + Sync + Send + 'static +
495  CompileConst + ConstElem + AsValueKind,
496  R1: Dim,
497  C1: Dim,
498  S1: StorageMut<T, R1, C1> + Clone + Debug,
499  naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
500{
501  fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
502    match args {
503      FunctionArgs::Ternary(out, arg1, arg2, arg3) => {
504        let source: Ref<T> = unsafe { arg1.as_unchecked() }.clone();
505        let ix1: Ref<usize> = unsafe { arg2.as_unchecked() }.clone();
506        let ix2: Ref<usize> = unsafe { arg3.as_unchecked() }.clone();
507        let sink: Ref<naMatrix<T, R1, C1, S1>> =
508        unsafe { out.as_unchecked() }.clone();
509        Ok(Box::new(Self {sink,source,ixes: (ix1, ix2),_marker: PhantomData}))
510      }
511      _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 3, found: args.len() }, None).with_compiler_loc()),
512    }
513  }
514}
515impl<T, R1, C1, S1> MechFunctionImpl for Assign2DSSS<T, naMatrix<T, R1, C1, S1>>
516where
517    Ref<naMatrix<T, R1, C1, S1>>: ToValue,
518    T: Scalar + Clone + Debug + Sync + Send + 'static,
519    R1: Dim,
520    C1: Dim,
521    S1: StorageMut<T, R1, C1> + Clone + Debug,
522{
523  fn solve(&self) {
524    unsafe {
525      let sink_ptr = &mut *self.sink.as_mut_ptr();
526      let source_val = (*self.source.as_ptr()).clone();
527      let r = (*self.ixes.0.as_ptr()).clone();
528      let c = (*self.ixes.1.as_ptr()).clone();
529      sink_ptr[(r - 1, c - 1)] = source_val;
530    }
531  }
532  fn out(&self) -> Value {self.sink.to_value()}
533  fn to_string(&self) -> String {format!("{:#?}", self)}
534}
535impl<T, R1, C1, S1> MechFunctionCompiler for Assign2DSSS<T, naMatrix<T, R1, C1, S1>>
536where
537  T: CompileConst + ConstElem + AsValueKind,
538  naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
539{
540  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
541    let name = format!("Assign2DSSS<{}{}>", T::as_value_kind(), naMatrix::<T, R1, C1, S1>::as_na_kind());
542    compile_ternop!(name, self.sink, self.source, self.ixes.0, self.ixes.1, ctx, FeatureFlag::Builtin(FeatureKind::Assign) );
543  }
544}
545
546fn impl_assign_scalar_scalar_fxn(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
547  let arg = (sink.clone(), ixes.as_slice(), source.clone());
548               impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, u8,   "u8")
549  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, u16,  "u16"))
550  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, u32,  "u32"))
551  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, u64,  "u64"))
552  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, u128, "u128"))
553  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, i8,   "i8"))
554  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, i16,  "i16"))
555  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, i32,  "i32"))
556  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, i64,  "i64"))
557  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, i128, "i128"))
558  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, f32,  "f32"))
559  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, f64,  "f64"))
560  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, R64,  "rational"))
561  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, C64,  "complex"))
562  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, bool, "bool"))
563  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_scalar_arms, Assign2DSS, arg, String, "string"))
564  .map_err(|_| MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignScalarScalar".to_string() }, None).with_compiler_loc())
565}
566
567pub struct MatrixAssignScalarScalar {}
568impl NativeFunctionCompiler for MatrixAssignScalarScalar {
569  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
570    if arguments.len() <= 1 {
571      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
572    }
573    let sink: Value = arguments[0].clone();
574    let source: Value = arguments[1].clone();
575    let ixes = arguments.clone().split_off(2);
576    match impl_assign_scalar_scalar_fxn(sink.clone(),source.clone(),ixes.clone()) {
577      Ok(fxn) => Ok(fxn),
578      Err(_) => {
579        match sink {
580          Value::MutableReference(sink) => { impl_assign_scalar_scalar_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) }
581          _ => Err(MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignScalarScalar".to_string() }, None).with_compiler_loc()),
582        }
583      }
584    }
585  }
586}
587
588// x[:,1] = 1 -----------------------------------------------------------------
589
590macro_rules! assign_2d_all_scalar {
591  ($source:expr, $ix:expr, $sink:expr) => {
592      for i in 0..$sink.nrows() {
593        ($sink).column_mut($ix - 1)[i] = ($source).clone();
594      }
595    };}
596
597macro_rules! assign_2d_all_vector {
598  ($source:expr, $ix:expr, $sink:expr) => {
599      for i in 0..$sink.nrows() {
600        ($sink).column_mut($ix - 1)[i] = ($source)[i].clone();
601      }
602    };}
603
604#[macro_export]
605macro_rules! impl_assign_scalar_fxn_v {
606  ($struct_name:ident, $op:ident, $ix:ty) => {
607    #[derive(Debug)]
608    pub struct $struct_name<T, MatA, MatB> {
609      pub source: Ref<MatB>,
610      pub ixes: Ref<$ix>,
611      pub sink: Ref<MatA>,
612      pub _marker: PhantomData<T>,
613    }
614    impl<T, R1: 'static, C1: 'static, S1: 'static, R2: 'static, C2: 'static, S2: 'static> MechFunctionFactory for $struct_name<T, naMatrix<T, R1, C1, S1>, naMatrix<T, R2, C2, S2>>
615    where
616      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
617      Ref<naMatrix<T, R2, C2, S2>>: ToValue,
618      T: Debug + Clone + Sync + Send + 'static +
619        PartialEq + PartialOrd +
620        CompileConst + ConstElem + AsValueKind,
621      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
622      R2: Dim, C2: Dim, S2: Storage<T, R2, C2> + Clone + Debug,
623      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + Debug + AsNaKind,
624      naMatrix<T, R2, C2, S2>: CompileConst + ConstElem + Debug + AsNaKind,
625    {
626      fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
627        match args {
628          FunctionArgs::Binary(out, arg1, arg2) => {
629            let source: Ref<naMatrix<T, R2, C2, S2>> = unsafe { arg1.as_unchecked() }.clone();
630            let ixes: Ref<$ix> = unsafe { arg2.as_unchecked() }.clone();
631            let sink: Ref<naMatrix<T, R1, C1, S1>> = unsafe { out.as_unchecked() }.clone();
632            Ok(Box::new(Self { sink, source, ixes, _marker: PhantomData::default() }))
633          },
634          _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 3, found: args.len() }, None).with_compiler_loc())
635        }
636      }
637    }
638    impl<T, R1, C1, S1, R2, C2, S2>
639      MechFunctionImpl for $struct_name<T, naMatrix<T, R1, C1, S1>, naMatrix<T, R2, C2, S2>>
640    where
641      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
642      T: Debug + Clone + Sync + Send + 'static +
643         PartialEq + PartialOrd,
644      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
645      R2: Dim, C2: Dim, S2: Storage<T, R2, C2> + Clone + Debug,
646    {
647      fn solve(&self) {
648        unsafe {
649          let sink_ptr = &mut *self.sink.as_mut_ptr();
650          let source_ptr = &*self.source.as_ptr();
651          let ix_ptr = &(*self.ixes.as_ptr());
652          $op!(source_ptr,ix_ptr,sink_ptr);
653        }
654      }
655      fn out(&self) -> Value {self.sink.to_value()}
656      fn to_string(&self) -> String {format!("{:#?}", self)}
657    }
658    #[cfg(feature = "compiler")]
659    impl<T, R1, C1, S1, R2, C2, S2> MechFunctionCompiler for $struct_name<T, naMatrix<T, R1, C1, S1>, naMatrix<T, R2, C2, S2>> 
660    where
661      T: CompileConst + ConstElem + AsValueKind,
662      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
663      naMatrix<T, R2, C2, S2>: CompileConst + ConstElem + AsNaKind,
664    {
665      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
666        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());
667        compile_binop!(name, self.sink, self.source, self.ixes, ctx, FeatureFlag::Builtin(FeatureKind::Assign));
668      }
669    }  
670  };}
671
672impl_assign_fxn_s!(Assign2DASS, assign_2d_all_scalar, usize);
673impl_assign_scalar_fxn_v!(Assign2DASV, assign_2d_all_vector, usize);
674
675fn impl_assign_all_scalar_fxn(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
676  let arg = (sink.clone(), ixes.as_slice(), source.clone());
677               impl_assign_all_scalar_arms!(Assign2DAS, &arg, u8,   "u8")
678  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, u16,  "u16"))
679  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, u32,  "u32"))
680  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, u64,  "u64"))
681  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, u128, "u128"))
682  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, i8,   "i8"))
683  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, i16,  "i16"))
684  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, i32,  "i32"))
685  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, i64,  "i64"))
686  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, i128, "i128"))
687  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, f32,  "f32"))
688  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, f64,  "f64"))
689  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, R64,  "rational"))
690  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, C64,  "complex"))
691  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, bool, "bool"))
692  .or_else(|_| impl_assign_all_scalar_arms!(Assign2DAS, &arg, String, "string"))
693  .map_err(|_| MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignRangeScalar".to_string() }, None).with_compiler_loc())
694}
695
696pub struct MatrixAssignAllScalar {}
697impl NativeFunctionCompiler for MatrixAssignAllScalar {
698  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
699    if arguments.len() <= 1 {
700      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
701    }
702    let sink: Value = arguments[0].clone();
703    let source: Value = arguments[1].clone();
704    let ixes = arguments.clone().split_off(2);
705    match impl_assign_all_scalar_fxn(sink.clone(),source.clone(),ixes.clone()) {
706      Ok(fxn) => Ok(fxn),
707      Err(x) => {
708        match sink {
709          Value::MutableReference(sink) => { impl_assign_all_scalar_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) }
710          sink => Err(MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignRangeScalar".to_string() }, None).with_compiler_loc()),
711        }
712      }
713    }
714  }
715}
716
717// x[1,:] = 1 -----------------------------------------------------------------
718
719macro_rules! assign_2d_scalar_all_scalar {
720  ($source:expr, $ix:expr, $sink:expr) => {
721    for i in 0..$sink.ncols() {
722      ($sink).row_mut($ix - 1)[i] = ($source).clone();
723    }
724  };}
725
726macro_rules! assign_2d_scalar_all_vector {
727  ($source:expr, $ix:expr, $sink:expr) => {
728    for i in 0..$sink.ncols() {
729      ($sink).row_mut($ix - 1)[i] = ($source)[i].clone();
730    }
731  };}
732
733impl_assign_fxn_s!(Assign2DSAS, assign_2d_scalar_all_scalar, usize);
734impl_assign_scalar_fxn_v!(Assign2DSAV, assign_2d_scalar_all_vector, usize);
735
736fn impl_assign_scalar_all_fxn(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
737  let arg = (sink.clone(), ixes.as_slice(), source.clone());
738               impl_assign_scalar_all_arms!(Assign2DSA, &arg, u8,   "u8")
739  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, u16,  "u16"))
740  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, u32,  "u32"))
741  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, u64,  "u64"))
742  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, u128, "u128"))
743  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, i8,   "i8"))
744  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, i16,  "i16"))
745  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, i32,  "i32"))
746  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, i64,  "i64"))
747  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, i128, "i128"))
748  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, f32,  "f32"))
749  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, f64,  "f64"))
750  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, R64,  "rational"))
751  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, C64,  "complex"))
752  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, bool, "bool"))
753  .or_else(|_| impl_assign_scalar_all_arms!(Assign2DSA, &arg, String, "string"))
754  .map_err(|_| MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignRangeScalar".to_string() }, None).with_compiler_loc())
755}
756
757pub struct MatrixAssignScalarAll {}
758impl NativeFunctionCompiler for MatrixAssignScalarAll {
759  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
760    if arguments.len() <= 1 {
761      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
762    }
763    let sink: Value = arguments[0].clone();
764    let source: Value = arguments[1].clone();
765    let ixes = arguments.clone().split_off(2);
766    match impl_assign_scalar_all_fxn(sink.clone(),source.clone(),ixes.clone()) {
767      Ok(fxn) => Ok(fxn),
768      Err(_) => {
769        match sink {
770          Value::MutableReference(sink) => { impl_assign_scalar_all_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) }
771          _ => Err(MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignRangeScalar".to_string() }, None).with_compiler_loc()),
772        }
773      }
774    }
775  }
776}
777
778// x[1..3,1] = 1 ------------------------------------------------------------------
779
780macro_rules! assign_2d_range_scalar {
781  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
782    unsafe { 
783      let mut col = ($sink).column_mut($ix2 - 1);
784      for &rix in ($ix1).iter() {
785        col[rix - 1] = ($source).clone();
786      }
787    }
788  };
789}
790
791macro_rules! assign_2d_range_scalar_v {
792  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
793    unsafe { 
794      let mut col = ($sink).column_mut($ix2 - 1);
795      for (i, &rix) in ($ix1).iter().enumerate() {
796        col[rix - 1] = ($source)[i].clone();
797      }
798    }
799  };
800}
801
802macro_rules! assign_2d_range_scalar_b {
803  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
804    unsafe { 
805      let mut col = ($sink).column_mut($ix2 - 1);
806      for (rix, &is_selected) in ($ix1).iter().enumerate() {
807        if is_selected {
808          col[rix] = ($source).clone();
809        }
810      }
811    }
812  };
813}
814
815macro_rules! assign_2d_range_scalar_vb {
816  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
817    unsafe { 
818      let mut col = ($sink).column_mut($ix2 - 1);
819      for (rix, &is_selected) in ($ix1).iter().enumerate() {
820        if is_selected {
821          col[rix] = ($source)[rix].clone();
822        }
823      }
824    }
825  };
826}
827
828#[macro_export]
829macro_rules! impl_assign_range_scalar_fxn_s {
830  ($struct_name:ident, $op:tt, $ix:ty) => {
831    #[derive(Debug)]
832    pub struct $struct_name<T, MatA, IxVec> {
833      pub source: Ref<T>,
834      pub ixes: (Ref<IxVec>, Ref<usize>),
835      pub sink: Ref<MatA>,
836      pub _marker: PhantomData<T>,
837    }
838    impl<T, R, C, S: 'static, IxVec: 'static> MechFunctionFactory for $struct_name<T, na::Matrix<T, R, C, S>, IxVec>
839    where
840      Ref<naMatrix<T, R, C, S>>: ToValue,
841      T: Scalar + Clone + Debug + Sync + Send + 'static + CompileConst + ConstElem + AsValueKind,
842      IxVec: CompileConst + ConstElem + Debug + AsRef<[$ix]> + AsNaKind,
843      R: Dim, C: Dim, S: StorageMut<T, R, C> + Clone + Debug,
844      naMatrix<T, R, C, S>: CompileConst + ConstElem + Debug + AsNaKind,
845    {
846      fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
847        match args {
848          FunctionArgs::Ternary(out, arg1, arg2, arg3) => {
849            let source: Ref<T> = unsafe { arg1.as_unchecked() }.clone();
850            let ix1: Ref<IxVec> = unsafe { arg2.as_unchecked() }.clone();
851            let ix2: Ref<usize> = unsafe { arg3.as_unchecked() }.clone();
852            let sink: Ref<na::Matrix<T, R, C, S>> = unsafe { out.as_unchecked() }.clone();
853            Ok(Box::new(Self { sink, source, ixes: (ix1, ix2), _marker: PhantomData }))
854          }
855          _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 3, found: args.len() }, None).with_compiler_loc())
856        }
857      }
858    }
859    impl<T, R, C, S, IxVec> MechFunctionImpl for $struct_name<T, na::Matrix<T, R, C, S>, IxVec>
860    where
861      Ref<naMatrix<T, R, C, S>>: ToValue,
862      T: Scalar + Clone + Debug + Sync + Send + 'static,
863      IxVec: AsRef<[$ix]> + Debug,
864      R: Dim, C: Dim, S: StorageMut<T, R, C> + Clone + Debug,
865    {
866      fn solve(&self) {
867        unsafe {
868          let sink = &mut *self.sink.as_mut_ptr();
869          let source = &*self.source.as_ptr();
870          let ix1 = (*self.ixes.0.as_ptr()).as_ref();
871          let ix2 = (*self.ixes.1.as_ptr());
872          $op!(sink, ix1, ix2, source);
873        }
874      }
875      fn out(&self) -> Value {self.sink.to_value()}
876      fn to_string(&self) -> String {format!("{:#?}", self)}
877    }
878    #[cfg(feature = "compiler")]
879    impl<T, R, C, S, IxVec> MechFunctionCompiler for $struct_name<T, na::Matrix<T, R, C, S>, IxVec> 
880    where
881      T: CompileConst + ConstElem + AsValueKind,
882      IxVec: CompileConst + ConstElem + AsNaKind,
883      naMatrix<T, R, C, S>: CompileConst + ConstElem + AsNaKind,
884    {
885      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
886        let name = format!("{}<{}{}{}>", stringify!($struct_name), T::as_value_kind(), naMatrix::<T, R, C, S>::as_na_kind(), IxVec::as_na_kind());
887        compile_ternop!(name, self.sink, self.source, self.ixes.0, self.ixes.1, ctx, FeatureFlag::Builtin(FeatureKind::Assign) );
888      }
889    }
890  };}
891
892#[macro_export]
893macro_rules! impl_assign_range_scalar_fxn_v {
894  ($struct_name:ident, $op:ident, $ix:ty) => {
895    #[derive(Debug)]
896    pub struct $struct_name<T, MatA, MatB, IxVec> {
897      pub source: Ref<MatB>,
898      pub ixes: (Ref<IxVec>, Ref<usize>),
899      pub sink: Ref<MatA>,
900      pub _marker: PhantomData<T>,
901    }
902    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>
903    where
904      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
905      Ref<naMatrix<T, R2, C2, S2>>: ToValue,
906      T: Debug + Clone + Sync + Send + 'static +
907        PartialEq + PartialOrd +
908        CompileConst + ConstElem + AsValueKind,
909      IxVec: CompileConst + ConstElem + AsNaKind + Debug + AsRef<[$ix]>,
910      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
911      R2: Dim, C2: Dim, S2: Storage<T, R2, C2> + Clone + Debug,
912      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + Debug + AsNaKind,
913      naMatrix<T, R2, C2, S2>: CompileConst + ConstElem + Debug + AsNaKind,
914    {
915      fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
916        match args {
917          FunctionArgs::Ternary(out, arg1, arg2, arg3) => {
918            let source: Ref<naMatrix<T, R2, C2, S2>> = unsafe { arg1.as_unchecked() }.clone();
919            let ix1: Ref<IxVec> = unsafe { arg2.as_unchecked() }.clone();
920            let ix2: Ref<usize> = unsafe { arg3.as_unchecked() }.clone();
921            let sink: Ref<naMatrix<T, R1, C1, S1>> = unsafe { out.as_unchecked() }.clone();
922            Ok(Box::new(Self { sink, source, ixes: (ix1, ix2), _marker: PhantomData::default() }))
923          },
924          _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 3, found: args.len() }, None).with_compiler_loc())
925        }
926      }
927    }
928    impl<T, R1, C1, S1, R2, C2, S2, IxVec>
929      MechFunctionImpl for $struct_name<T, naMatrix<T, R1, C1, S1>, naMatrix<T, R2, C2, S2>, IxVec>
930    where
931      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
932      T: Debug + Clone + Sync + Send + 'static +
933         PartialEq + PartialOrd,
934      IxVec: AsRef<[$ix]> + Debug,
935      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
936      R2: Dim, C2: Dim, S2: Storage<T, R2, C2> + Clone + Debug,
937    {
938      fn solve(&self) {
939        unsafe {
940          let sink = &mut *self.sink.as_mut_ptr();
941          let source = &*self.source.as_ptr();
942          let ix1 = (*self.ixes.0.as_ptr()).as_ref();
943          let ix2 = (*self.ixes.1.as_ptr());
944          $op!(sink, ix1, ix2, source);
945        }
946      }
947      fn out(&self) -> Value {self.sink.to_value()}
948      fn to_string(&self) -> String {format!("{:#?}", self)}
949    }
950    #[cfg(feature = "compiler")]
951    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> 
952    where
953      T: CompileConst + ConstElem + AsValueKind,
954      IxVec: CompileConst + ConstElem + AsNaKind,
955      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
956      naMatrix<T, R2, C2, S2>: CompileConst + ConstElem + AsNaKind,
957    {
958      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
959        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());
960        compile_ternop!(name, self.sink, self.source, self.ixes.0, self.ixes.1, ctx, FeatureFlag::Builtin(FeatureKind::Assign) );  
961      }
962    }  
963  };}
964
965impl_assign_range_scalar_fxn_s!(Assign2DSSMD, assign_2d_range_scalar, usize);
966
967impl_assign_range_scalar_fxn_s!(Assign2DRSS, assign_2d_range_scalar, usize);
968impl_assign_range_scalar_fxn_s!(Assign2DRSB, assign_2d_range_scalar_b, bool);
969impl_assign_range_scalar_fxn_v!(Assign2DRSV, assign_2d_range_scalar_v, usize);
970impl_assign_range_scalar_fxn_v!(Assign2DRSVB, assign_2d_range_scalar_vb, bool);
971
972fn impl_assign_range_scalar_fxn(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
973  let arg = (sink.clone(), ixes.as_slice(), source.clone());
974               impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, u8,   "u8")
975  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, u16,  "u16"))
976  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, u32,  "u32"))
977  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, u64,  "u64"))
978  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, u128, "u128"))
979  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, i8,   "i8"))
980  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, i16,  "i16"))
981  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, i32,  "i32"))
982  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, i64,  "i64"))
983  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, i128, "i128"))
984  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, f32,  "f32"))
985  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, f64,  "f64"))
986  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, R64,  "rational"))
987  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, C64,  "complex"))
988  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, bool, "bool"))
989  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms, Assign2DRS, arg, String, "string"))
990
991  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, u8,  "u8"))
992  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, u16,  "u16"))
993  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, u32,  "u32"))
994  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, u64,  "u64"))
995  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, u128, "u128"))
996  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, i8,   "i8"))
997  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, i16,  "i16"))
998  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, i32,  "i32"))
999  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, i64,  "i64"))
1000  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, i128, "i128"))
1001  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, f32,  "f32"))
1002  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, f64,  "f64"))
1003  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, R64,  "rational"))
1004  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, C64,  "complex"))
1005  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, bool, "bool"))
1006  .or_else(|_| impl_assign_fxn!(impl_assign_range_scalar_arms_b, Assign2DRS, arg, String, "string"))
1007  .map_err(|_| MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignRangeScalar".to_string() }, None).with_compiler_loc())
1008}
1009
1010pub struct MatrixAssignRangeScalar {}
1011impl NativeFunctionCompiler for MatrixAssignRangeScalar {
1012  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
1013    if arguments.len() <= 1 {
1014      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
1015    }
1016    let sink: Value = arguments[0].clone();
1017    let source: Value = arguments[1].clone();
1018    let ixes = arguments.clone().split_off(2);
1019    match impl_assign_range_scalar_fxn(sink.clone(),source.clone(),ixes.clone()) {
1020      Ok(fxn) => Ok(fxn),
1021      Err(_) => {
1022        match sink {
1023          Value::MutableReference(sink) => { impl_assign_range_scalar_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) }
1024          _ => Err(MechError2::new(UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignRangeScalar".to_string() }, None).with_compiler_loc()),
1025        }
1026      }
1027    }
1028  }
1029}
1030
1031// x[1,1..3] = 1 ------------------------------------------------------------------
1032
1033macro_rules! assign_2d_scalar_range {
1034  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1035    unsafe { 
1036      for i in 0..($ix2).len() {
1037        let cix = $ix2[i] - 1; 
1038        ($sink).row_mut($ix1 - 1)[cix] = ($source).clone();
1039      }
1040    }
1041  };}
1042
1043macro_rules! assign_2d_scalar_range_v {
1044  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1045    unsafe { 
1046      for i in 0..($ix2).len() {
1047        let cix = $ix2[i] - 1; 
1048        ($sink).row_mut($ix1 - 1)[cix] = ($source)[i].clone();
1049      }
1050    }
1051  };
1052}
1053
1054macro_rules! assign_2d_scalar_range_b {
1055  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1056    unsafe { 
1057      for cix in 0..($ix2).len() {
1058        if $ix2[cix] == true {
1059          ($sink).row_mut($ix1 - 1)[cix] = ($source).clone();
1060        }
1061      }
1062    }
1063  };}
1064
1065macro_rules! assign_2d_scalar_range_vb {
1066  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1067    unsafe { 
1068      for cix in 0..($ix2).len() {
1069        if $ix2[cix] == true {
1070          ($sink).row_mut($ix1 - 1)[cix] = ($source)[cix].clone();
1071        }
1072      }
1073    }
1074  };}
1075
1076#[macro_export]
1077macro_rules! impl_assign_scalar_range_fxn_s {
1078  ($struct_name:ident, $op:tt, $ix:ty) => {
1079    #[derive(Debug)]
1080    pub struct $struct_name<T, MatA, IxVec> {
1081      pub source: Ref<T>,
1082      pub ixes: (Ref<usize>,Ref<IxVec>),
1083      pub sink: Ref<MatA>,
1084      pub _marker: PhantomData<T>,
1085    }
1086    impl<T, R, C, S: 'static, IxVec: 'static> MechFunctionFactory for $struct_name<T, na::Matrix<T, R, C, S>, IxVec>
1087    where
1088      Ref<naMatrix<T, R, C, S>>: ToValue,
1089      T: Scalar + Clone + Debug + Sync + Send + 'static + CompileConst + ConstElem + AsValueKind,
1090      IxVec: CompileConst + ConstElem + Debug + AsRef<[$ix]> + AsNaKind,
1091      R: Dim, C: Dim, S: StorageMut<T, R, C> + Clone + Debug,
1092      naMatrix<T, R, C, S>: CompileConst + ConstElem + Debug + AsNaKind,
1093    {
1094      fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
1095        match args {
1096          FunctionArgs::Ternary(out, arg1, arg2, arg3) => {
1097            let source: Ref<T> = unsafe { arg1.as_unchecked() }.clone();
1098            let ix1: Ref<usize> = unsafe { arg2.as_unchecked() }.clone();
1099            let ix2: Ref<IxVec> = unsafe { arg3.as_unchecked() }.clone();
1100            let sink: Ref<na::Matrix<T, R, C, S>> = unsafe { out.as_unchecked() }.clone();
1101            Ok(Box::new(Self { sink, source, ixes: (ix1, ix2), _marker: PhantomData }))
1102          }
1103          _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 3, found: args.len() }, None).with_compiler_loc())
1104        }
1105      }
1106    }
1107    impl<T, R, C, S, IxVec> MechFunctionImpl for $struct_name<T, na::Matrix<T, R, C, S>, IxVec>
1108    where
1109      Ref<naMatrix<T, R, C, S>>: ToValue,
1110      T: Scalar + Clone + Debug + Sync + Send + 'static,
1111      IxVec: AsRef<[$ix]> + Debug,
1112      R: Dim, C: Dim, S: StorageMut<T, R, C> + Clone + Debug,
1113    {
1114      fn solve(&self) {
1115        unsafe {
1116          let sink = &mut *self.sink.as_mut_ptr();
1117          let source = &*self.source.as_ptr();
1118          let ix1 = (*self.ixes.0.as_ptr());
1119          let ix2 = (*self.ixes.1.as_ptr()).as_ref();
1120          $op!(sink, ix1, ix2, source);
1121        }
1122      }
1123      fn out(&self) -> Value {self.sink.to_value()}
1124      fn to_string(&self) -> String {format!("{:#?}", self)}
1125    }
1126    #[cfg(feature = "compiler")]
1127    impl<T, R, C, S, IxVec> MechFunctionCompiler for $struct_name<T, na::Matrix<T, R, C, S>, IxVec> 
1128    where
1129      T: CompileConst + ConstElem + AsValueKind,
1130      IxVec: CompileConst + ConstElem + AsNaKind,
1131      naMatrix<T, R, C, S>: CompileConst + ConstElem + AsNaKind,
1132    {
1133      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
1134        let name = format!("{}<{}{}{}>", stringify!($struct_name), T::as_value_kind(), naMatrix::<T, R, C, S>::as_na_kind(), IxVec::as_na_kind());
1135        compile_ternop!(name, self.sink, self.source, self.ixes.0, self.ixes.1, ctx, FeatureFlag::Builtin(FeatureKind::Assign) );
1136      }
1137    }
1138  };}
1139
1140#[macro_export]
1141macro_rules! impl_assign_scalar_range_fxn_v {
1142  ($struct_name:ident, $op:ident, $ix:ty) => {
1143    #[derive(Debug)]
1144    pub struct $struct_name<T, MatA, MatB, IxVec> {
1145      pub source: Ref<MatB>,
1146      pub ixes: (Ref<usize>,Ref<IxVec>),
1147      pub sink: Ref<MatA>,
1148      pub _marker: PhantomData<T>,
1149    }
1150    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>
1151    where
1152      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
1153      Ref<naMatrix<T, R2, C2, S2>>: ToValue,
1154      T: Debug + Clone + Sync + Send + 'static +
1155        PartialEq + PartialOrd +
1156        CompileConst + ConstElem + AsValueKind,
1157      IxVec: CompileConst + ConstElem + AsNaKind + Debug + AsRef<[$ix]>,
1158      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
1159      R2: Dim, C2: Dim, S2: Storage<T, R2, C2> + Clone + Debug,
1160      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + Debug + AsNaKind,
1161      naMatrix<T, R2, C2, S2>: CompileConst + ConstElem + Debug + AsNaKind,
1162    {
1163      fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
1164        match args {
1165          FunctionArgs::Ternary(out, arg1, arg2, arg3) => {
1166            let source: Ref<naMatrix<T, R2, C2, S2>> = unsafe { arg1.as_unchecked() }.clone();
1167            let ix1: Ref<usize> = unsafe { arg2.as_unchecked() }.clone();
1168            let ix2: Ref<IxVec> = unsafe { arg3.as_unchecked() }.clone();
1169            let sink: Ref<naMatrix<T, R1, C1, S1>> = unsafe { out.as_unchecked() }.clone();
1170            Ok(Box::new(Self { sink, source, ixes: (ix1, ix2), _marker: PhantomData::default() }))
1171          },
1172          _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 3, found: args.len() }, None).with_compiler_loc())
1173        }
1174      }
1175    }
1176    impl<T, R1, C1, S1, R2, C2, S2, IxVec>
1177      MechFunctionImpl for $struct_name<T, naMatrix<T, R1, C1, S1>, naMatrix<T, R2, C2, S2>, IxVec>
1178    where
1179      Ref<naMatrix<T, R1, C1, S1>>: ToValue,
1180      T: Debug + Clone + Sync + Send + 'static +
1181         PartialEq + PartialOrd,
1182      IxVec: AsRef<[$ix]> + Debug,
1183      R1: Dim, C1: Dim, S1: StorageMut<T, R1, C1> + Clone + Debug,
1184      R2: Dim, C2: Dim, S2: Storage<T, R2, C2> + Clone + Debug,
1185    {
1186      fn solve(&self) {
1187        unsafe {
1188          let sink = &mut *self.sink.as_mut_ptr();
1189          let source = &*self.source.as_ptr();
1190          let ix1 = (*self.ixes.0.as_ptr());
1191          let ix2 = (*self.ixes.1.as_ptr()).as_ref();
1192          $op!(sink, ix1, ix2, source);
1193        }
1194      }
1195      fn out(&self) -> Value {self.sink.to_value()}
1196      fn to_string(&self) -> String {format!("{:#?}", self)}
1197    }
1198    #[cfg(feature = "compiler")]
1199    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> 
1200    where
1201      T: CompileConst + ConstElem + AsValueKind,
1202      IxVec: CompileConst + ConstElem + AsNaKind,
1203      naMatrix<T, R1, C1, S1>: CompileConst + ConstElem + AsNaKind,
1204      naMatrix<T, R2, C2, S2>: CompileConst + ConstElem + AsNaKind,
1205    {
1206      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
1207        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());
1208        compile_ternop!(name, self.sink, self.source, self.ixes.0, self.ixes.1, ctx, FeatureFlag::Builtin(FeatureKind::Assign) );  
1209      }
1210    }  
1211  };}
1212
1213impl_assign_scalar_range_fxn_s!(Assign2DSRS,  assign_2d_scalar_range, usize);
1214impl_assign_scalar_range_fxn_s!(Assign2DSRB,  assign_2d_scalar_range_b, bool);
1215impl_assign_scalar_range_fxn_v!(Assign2DSRV,  assign_2d_scalar_range_v, usize);
1216impl_assign_scalar_range_fxn_v!(Assign2DSRVB, assign_2d_scalar_range_vb, bool);
1217
1218fn impl_assign_scalar_range_fxn(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
1219  let arg = (sink.clone(), ixes.as_slice(), source.clone());
1220               impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, u8,   "u8")
1221  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, u16,  "u16"))
1222  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, u32,  "u32"))
1223  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, u64,  "u64"))
1224  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, u128, "u128"))
1225  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, i8,   "i8"))
1226  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, i16,  "i16"))
1227  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, i32,  "i32"))
1228  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, i64,  "i64"))
1229  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, i128, "i128"))
1230  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, f32,  "f32"))
1231  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, f64,  "f64"))
1232  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, R64,  "rational"))
1233  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, C64,  "complex"))
1234  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, bool, "bool"))
1235  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms, Assign2DSR, arg, String, "string"))
1236
1237  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, u8,  "u8"))
1238  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, u16,  "u16"))
1239  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, u32,  "u32"))
1240  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, u64,  "u64"))
1241  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, u128, "u128"))
1242  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, i8,   "i8"))
1243  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, i16,  "i16"))
1244  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, i32,  "i32"))
1245  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, i64,  "i64"))
1246  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, i128, "i128"))
1247  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, f32,  "f32"))
1248  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, f64,  "f64"))
1249  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, R64,  "rational"))
1250  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, C64,  "complex"))
1251  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, bool, "bool"))
1252  .or_else(|_| impl_assign_fxn!(impl_assign_scalar_range_arms_b, Assign2DSR, arg, String, "string"))
1253  .map_err(|_| MechError2::new(
1254    UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|x| x.kind()).collect(), source.kind()), fxn_name: "MatrixAssignScalarRange".to_string()  }, None).with_compiler_loc()
1255  )
1256}
1257
1258pub struct MatrixAssignScalarRange {}
1259impl NativeFunctionCompiler for MatrixAssignScalarRange {
1260  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
1261    if arguments.len() <= 1 {
1262      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
1263    }
1264    let sink: Value = arguments[0].clone();
1265    let source: Value = arguments[1].clone();
1266    let ixes = arguments.clone().split_off(2);
1267    match impl_assign_scalar_range_fxn(sink.clone(),source.clone(),ixes.clone()) {
1268      Ok(fxn) => Ok(fxn),
1269      Err(_) => {
1270        match sink {
1271          Value::MutableReference(sink) => { impl_assign_scalar_range_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) }
1272          _ => Err(MechError2::new(
1273            UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "MatrixAssignScalarRange".to_string() }, None).with_compiler_loc() ),
1274        }
1275      }
1276    }
1277  }
1278}
1279
1280// x[1..3,1..3] = 1 ------------------------------------------------------------------
1281
1282macro_rules! assign_2d_range_range {
1283  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1284    unsafe { 
1285      for rix in 0..($ix1).len() {
1286        let r = $ix1[rix] - 1;
1287        for cix in 0..($ix2).len() {
1288          let c = $ix2[cix] - 1;
1289          ($sink)[(r, c)] = ($source).clone();
1290        }
1291      }
1292    }
1293  };}
1294
1295macro_rules! assign_2d_range_range_v {
1296  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1297    unsafe { 
1298      for rix in 0..($ix1).len() {
1299        let r = $ix1[rix] - 1;
1300        for cix in 0..($ix2).len() {
1301          let c = $ix2[cix] - 1;
1302          ($sink)[(r, c)] = ($source)[rix * ($ix2).len() + cix].clone();
1303        }
1304      }
1305    }
1306  };}
1307
1308macro_rules! assign_2d_range_range_b {
1309  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1310    unsafe { 
1311      for r in 0..($ix1).len() {
1312        if $ix1[r] == true {
1313          for c in 0..($ix2).len() {
1314            if $ix2[c] == true {
1315              ($sink)[(r, c)] = ($source).clone();
1316            }
1317          }
1318        }
1319      }
1320    }
1321  };}
1322
1323macro_rules! assign_2d_range_range_vb {
1324  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1325    unsafe { 
1326      for r in 0..($ix1).len() {
1327        if $ix1[r] == true {
1328          for c in 0..($ix2).len() {
1329            if $ix2[c] == true {
1330              ($sink)[(r, c)] = ($source)[r * ($ix2).len() + c].clone();
1331            }
1332          }
1333        }
1334      }
1335    }
1336  };}
1337
1338macro_rules! assign_2d_range_range_bu {
1339  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1340    unsafe {
1341      for r in 0..($ix1).len() {
1342        if $ix1[r] == true {
1343          for cix in 0..($ix2).len() {
1344            let c = $ix2[cix] - 1;
1345            ($sink)[(r, c)] = ($source).clone();
1346          }
1347        }
1348      }
1349    }
1350  };
1351}
1352
1353macro_rules! assign_2d_range_range_vbu {
1354  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1355    unsafe {
1356      let nrows = $sink.nrows();
1357      for cix in 0..($ix2).len() {
1358        let c = $ix2[cix] - 1;
1359        for r in 0..($ix1).len() {
1360          if $ix1[r] {
1361            let offset = r + c * nrows;
1362            ($sink)[(r, c)] = ($source)[offset].clone();
1363          }
1364        }
1365      }
1366    }
1367  };
1368}
1369
1370macro_rules! assign_2d_range_range_ub {
1371  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1372    unsafe {
1373      for r in 0..$ix1.len() {
1374        if $ix1[r] != 0 {
1375          for c in 0..$ix2.len() {
1376            if $ix2[c] {
1377              ($sink)[(r, c)] = $source.clone();
1378            }
1379          }
1380        }
1381      }
1382    }
1383  };
1384}
1385
1386macro_rules! assign_2d_range_range_vub {
1387  ($sink:expr, $ix1:expr, $ix2:expr, $source:expr) => {
1388    unsafe {
1389      let nrows = $sink.nrows();
1390      for c in 0..$ix2.len() {
1391        if $ix2[c] {
1392          for rix in 0..$ix1.len() {
1393            let r = $ix1[rix] - 1;
1394            let offset = r + c * nrows;
1395            ($sink)[(r, c)] = ($source)[offset].clone();
1396          }
1397        }
1398      }
1399    }
1400  };
1401}
1402
1403#[macro_export]
1404macro_rules! impl_assign_range_range_fxn_s {
1405  ($struct_name:ident, $op:tt, $ix1:ty, $ix2:ty) => {
1406    #[derive(Debug)]
1407    pub struct $struct_name<T, MatA, IxVec1, IxVec2> {
1408      pub source: Ref<T>,
1409      pub ixes: (Ref<IxVec1>,Ref<IxVec2>),
1410      pub sink: Ref<MatA>,
1411      pub _marker: PhantomData<T>,
1412    }
1413    impl<T, R, C, S: 'static, IxVec1: 'static, IxVec2: 'static> MechFunctionFactory for $struct_name<T, na::Matrix<T, R, C, S>, IxVec1, IxVec2>
1414    where
1415      Ref<naMatrix<T, R, C, S>>: ToValue,
1416      T: Scalar + Clone + Debug + Sync + Send + 'static + CompileConst + ConstElem + AsValueKind,
1417      IxVec1: CompileConst + ConstElem + Debug + AsRef<[$ix1]> + AsNaKind,
1418      IxVec2: CompileConst + ConstElem + Debug + AsRef<[$ix2]> + AsNaKind,
1419      R: Dim, C: Dim, S: StorageMut<T, R, C> + Clone + Debug,
1420      naMatrix<T, R, C, S>: CompileConst + ConstElem + Debug + AsNaKind,
1421    {
1422      fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
1423        match args {
1424          FunctionArgs::Ternary(out, arg1, arg2, arg3) => {
1425            let source: Ref<T> = unsafe { arg1.as_unchecked() }.clone();
1426            let ix1: Ref<IxVec1> = unsafe { arg2.as_unchecked() }.clone();
1427            let ix2: Ref<IxVec2> = unsafe { arg3.as_unchecked() }.clone();
1428            let sink: Ref<na::Matrix<T, R, C, S>> = unsafe { out.as_unchecked() }.clone();
1429            Ok(Box::new(Self { sink, source, ixes: (ix1, ix2), _marker: PhantomData }))
1430          }
1431          _ => Err(MechError2::new(
1432            IncorrectNumberOfArguments{expected: 3, found: args.len()},
1433            None
1434          ).with_compiler_loc()),
1435        }
1436      }
1437    }
1438    impl<T, R, C, S, IxVec1, IxVec2> MechFunctionImpl for $struct_name<T, na::Matrix<T, R, C, S>, IxVec1, IxVec2>
1439    where
1440      Ref<naMatrix<T, R, C, S>>: ToValue,
1441      T: Scalar + Clone + Debug + Sync + Send + 'static,
1442      IxVec1: AsRef<[$ix1]> + Debug,
1443      IxVec2: AsRef<[$ix2]> + Debug,
1444      R: Dim, C: Dim, S: StorageMut<T, R, C> + Clone + Debug,
1445    {
1446      fn solve(&self) {
1447        unsafe {
1448          let sink = &mut *self.sink.as_mut_ptr();
1449          let source = &*self.source.as_ptr();
1450          let ix1 = (*self.ixes.0.as_ptr()).as_ref();
1451          let ix2 = (*self.ixes.1.as_ptr()).as_ref();
1452          $op!(sink, ix1, ix2, source);
1453        }
1454      }
1455      fn out(&self) -> Value {self.sink.to_value()}
1456      fn to_string(&self) -> String {format!("{:#?}", self)}
1457    }
1458    #[cfg(feature = "compiler")]
1459    impl<T, R, C, S, IxVec1, IxVec2> MechFunctionCompiler for $struct_name<T, na::Matrix<T, R, C, S>, IxVec1, IxVec2> 
1460    where
1461      T: CompileConst + ConstElem + AsValueKind,
1462      IxVec1: CompileConst + ConstElem + AsNaKind,
1463      IxVec2: CompileConst + ConstElem + AsNaKind,
1464      naMatrix<T, R, C, S>: CompileConst + ConstElem + AsNaKind,
1465    {
1466      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
1467        let name = format!("{}<{}{}{}{}>", stringify!($struct_name), T::as_value_kind(), naMatrix::<T, R, C, S>::as_na_kind(), IxVec1::as_na_kind(), IxVec2::as_na_kind());
1468        compile_ternop!(name, self.sink, self.source, self.ixes.0, self.ixes.1, ctx, FeatureFlag::Builtin(FeatureKind::Assign) );
1469      }
1470    }
1471  };}
1472
1473impl_assign_range_range_fxn_s!(Assign2DRRS,   assign_2d_range_range,     usize, usize);
1474impl_range_range_fxn_v!(Assign2DRRV,   assign_2d_range_range_v,   usize, usize);
1475
1476impl_assign_range_range_fxn_s!(Assign2DRRBB,  assign_2d_range_range_b,   bool,  bool);
1477impl_range_range_fxn_v!(Assign2DRRVBB, assign_2d_range_range_vb,  bool,  bool);
1478
1479impl_assign_range_range_fxn_s!(Assign2DRRBU,  assign_2d_range_range_bu,  bool,  usize);
1480impl_range_range_fxn_v!(Assign2DRRVBU, assign_2d_range_range_vbu, bool,  usize);
1481
1482impl_assign_range_range_fxn_s!(Assign2DRRUB,  assign_2d_range_range_ub,  usize, bool);
1483impl_range_range_fxn_v!(Assign2DRRVUB, assign_2d_range_range_vub, usize, bool);
1484
1485
1486fn impl_assign_range_range_fxn(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
1487  let arg = (sink.clone(), ixes.as_slice(), source.clone());
1488               impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, u8, "u8")
1489  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, u16, "u16"))
1490  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, u32, "u32"))
1491  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, u64, "u64"))
1492  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, u128, "u128"))
1493  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, i8, "i8"))
1494  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, i16, "i16"))
1495  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, i32, "i32"))
1496  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, i64, "i64"))
1497  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, i128, "i128"))
1498  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, f32, "f32"))
1499  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, f64, "f64"))
1500  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, R64, "rational"))
1501  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, C64, "complex"))
1502  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, bool, "bool"))
1503  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms, Assign2DRR, arg, String, "string"))
1504
1505  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, u8,  "u8"))
1506  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, u16, "u16"))
1507  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, u32, "u32"))
1508  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, u64, "u64"))
1509  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, u128,"u128"))
1510  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, i8,  "i8"))
1511  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, i16, "i16"))
1512  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, i32, "i32"))
1513  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, i64, "i64"))
1514  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, i128,"i128"))
1515  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, f32, "f32"))
1516  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, f64, "f64"))
1517  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, R64, "rational"))
1518  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, C64, "complex"))
1519  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, bool, "bool"))
1520  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_b, Assign2DRR, arg, String, "string"))
1521
1522  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_bu, Assign2DRR, arg, f64, "f64"))
1523
1524  .or_else(|_| impl_assign_fxn!(impl_assign_range_range_arms_ub, Assign2DRR, arg, f64, "f64"))
1525
1526  .map_err(|_| MechError2::new(
1527      UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|x| x.kind()).collect(), source.kind()), fxn_name: "matrix/assign-range".to_string() },
1528      None
1529    ).with_compiler_loc()
1530  )
1531}
1532
1533pub struct MatrixAssignRangeRange {}
1534impl NativeFunctionCompiler for MatrixAssignRangeRange {
1535  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
1536    if arguments.len() <= 1 {
1537      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
1538    }
1539    let sink: Value = arguments[0].clone();
1540    let source: Value = arguments[1].clone();
1541    let ixes = arguments.clone().split_off(2);
1542    match impl_assign_range_range_fxn(sink.clone(),source.clone(),ixes.clone()) {
1543      Ok(fxn) => Ok(fxn),
1544      Err(_) => {
1545        match sink {
1546          Value::MutableReference(sink) => { impl_assign_range_range_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) }
1547          _ => Err(MechError2::new(
1548              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "matrix/assign-range".to_string() },
1549              None
1550            ).with_compiler_loc()
1551          ),
1552        }
1553      }
1554    }
1555  }
1556}
1557
1558// x[:,1..3] = 1 ------------------------------------------------------------------
1559
1560macro_rules! assign_2d_all_range {
1561  ($source:expr, $ix:expr, $sink:expr) => {
1562      for cix in $ix.iter() {
1563        for rix in 0..($sink).nrows() {
1564          ($sink).column_mut(cix - 1)[rix] = ($source).clone();
1565        }
1566      }
1567    };}
1568
1569macro_rules! assign_2d_all_range_b {
1570  ($source:expr, $ix:expr, $sink:expr) => {
1571    for cix in 0..$ix.len() {
1572      for rix in 0..($sink).nrows() {
1573        if $ix[cix] == true {
1574          ($sink).column_mut(cix)[rix] = ($source).clone();
1575        }
1576      }
1577    }
1578  };} 
1579
1580macro_rules! assign_2d_all_range_v {
1581  ($source:expr, $ix:expr, $sink:expr) => {
1582    {
1583      let nsrc = $source.nrows();
1584      for (i, &cix) in $ix.iter().enumerate() {
1585        let col_index = cix - 1;
1586        let mut sink_col = $sink.column_mut(col_index);
1587        let src_col = $source.column(i % nsrc); // wrap around!
1588        for (dst, src) in sink_col.iter_mut().zip(src_col.iter()) {
1589          *dst = src.clone();
1590        }
1591      }
1592    }
1593  };}
1594
1595macro_rules! assign_2d_all_range_vb {
1596  ($source:expr, $ix:expr, $sink:expr) => {
1597    {
1598      let mut src_i = 0;
1599      for (i, cix) in (&$ix).iter().enumerate() {
1600        if *cix == true {
1601          let mut sink_col = ($sink).column_mut(i);
1602          let src_col = ($source).column(src_i);
1603          for (dst, src) in sink_col.iter_mut().zip(src_col.iter()) {
1604            *dst = src.clone();
1605          }
1606          src_i += 1;
1607        }
1608      }
1609    }
1610  };}
1611
1612impl_all_fxn_v!(Set2DARV, assign_2d_all_range_v, usize);
1613impl_set_all_fxn_s!(Set2DARS, assign_2d_all_range, usize);
1614impl_set_all_fxn_s!(Set2DARB, assign_2d_all_range_b, bool);
1615impl_all_fxn_v!(Set2DARVB, assign_2d_all_range_vb, bool);
1616
1617macro_rules! matrix_assign_all_range_fxn {
1618  ($op_fxn_name:tt, $fxn_name:ident) => {
1619    paste::paste! {
1620      fn $op_fxn_name(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
1621        let arg = (sink.clone(), ixes.as_slice(), source.clone());
1622                     impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, u8, "u8")
1623        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, u16, "u16"))
1624        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, u32, "u32"))
1625        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, u64, "u64"))
1626        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, u128, "u128"))
1627        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, i8, "i8"))
1628        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, i16, "i16"))
1629        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, i32, "i32"))
1630        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, i64, "i64"))
1631        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, i128, "i128"))
1632        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, f32, "f32"))
1633        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, f64, "f64"))
1634        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, R64, "rational"))
1635        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, C64, "complex"))
1636        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, bool, "bool"))
1637        .or_else(|_| impl_assign_fxn!(impl_assign_all_range_arms, $fxn_name, arg, String, "string"))
1638
1639        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, u8,  "u8"))
1640        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, u16, "u16"))
1641        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, u32, "u32"))
1642        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, u64, "u64"))
1643        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, u128,"u128"))
1644        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, i8,  "i8"))
1645        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, i16, "i16"))
1646        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, i32, "i32"))
1647        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, i64, "i64"))
1648        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, i128,"i128"))
1649        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, f32, "f32"))
1650        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, f64, "f64"))
1651        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, R64, "rational"))
1652        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, C64, "complex"))
1653        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, bool, "bool"))
1654        .or_else(|_| impl_set_all_range_arms_b!($fxn_name, &arg, String, "string"))
1655        .map_err(|_| MechError2::new(
1656            UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "matrix/assign-scalar".to_string() },
1657            None
1658          ).with_compiler_loc()
1659        )
1660      }
1661    }
1662  }
1663}
1664
1665matrix_assign_all_range_fxn!(impl_assign_all_range_fxn, Set2DAR);
1666
1667pub struct MatrixAssignAllRange {}
1668impl NativeFunctionCompiler for MatrixAssignAllRange {
1669  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
1670    if arguments.len() <= 1 {
1671      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
1672    }
1673    let sink: Value = arguments[0].clone();
1674    let source: Value = arguments[1].clone();
1675    let ixes = arguments.clone().split_off(2);
1676    match impl_assign_all_range_fxn(sink.clone(), source.clone(), ixes.clone()) {
1677      Ok(fxn) => Ok(fxn),
1678      Err(_) => {
1679        match (sink.clone(), ixes.clone(), source.clone()) {
1680          (Value::MutableReference(sink), ixes, Value::MutableReference(source)) => { impl_assign_all_range_fxn(sink.borrow().clone(), source.borrow().clone(), ixes.clone()) },
1681          (sink, ixes, Value::MutableReference(source)) => { impl_assign_all_range_fxn(sink.clone(), source.borrow().clone(), ixes.clone()) },
1682          (Value::MutableReference(sink), ixes, source) => { impl_assign_all_range_fxn(sink.borrow().clone(), source.clone(), ixes.clone()) },
1683          (sink, ixes, source) => Err(MechError2::new(
1684            UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "matrix/assign-scalar".to_string() },
1685            None
1686          ).with_compiler_loc())
1687        }
1688      }
1689    }
1690  }
1691}
1692
1693// x[1..3,:] = 1 ------------------------------------------------------------------
1694
1695macro_rules! assign_2d_range_all {
1696  ($source:expr, $ix:expr, $sink:expr) => {
1697      for cix in 0..($sink).ncols() {
1698        for rix in $ix.iter() {
1699          ($sink).column_mut(cix)[rix - 1] = ($source).clone();
1700        }
1701      }
1702    };}
1703
1704macro_rules! assign_2d_range_all_b {
1705  ($source:expr, $ix:expr, $sink:expr) => {
1706    for cix in 0..($sink).ncols() {
1707      for rix in 0..$ix.len() {
1708        if $ix[rix] == true {
1709          ($sink).column_mut(cix)[rix - 1] = ($source).clone();
1710        }
1711      }
1712    }
1713  };} 
1714
1715  macro_rules! assign_2d_range_all_v {
1716  ($source:expr, $ix:expr, $sink:expr) => {
1717    {
1718      let nsrc = $source.nrows();
1719      for (i, &rix) in $ix.iter().enumerate() {
1720        let row_index = rix - 1;
1721        let mut sink_row = $sink.row_mut(row_index);
1722        let src_row = $source.row(i % nsrc); // wrap around!
1723        for (dst, src) in sink_row.iter_mut().zip(src_row.iter()) {
1724          *dst = src.clone();
1725        }
1726      }
1727    }
1728  };}
1729
1730macro_rules! assign_2d_range_all_vb {
1731  ($source:expr, $ix:expr, $sink:expr) => {
1732    {
1733      for (i, rix) in ($ix).iter().enumerate() {
1734        if *rix {
1735          let mut sink_row = ($sink).row_mut(i);
1736          let src_row = ($source).row(i);
1737          for (dst, src) in sink_row.iter_mut().zip(src_row.iter()) {
1738            *dst = src.clone();
1739          }
1740        }
1741      }
1742    }
1743  };
1744}
1745
1746impl_all_fxn_v!(Set2DRAV,assign_2d_range_all_v,usize);
1747impl_set_all_fxn_s!(Set2DRAS,assign_2d_range_all,usize);
1748impl_set_all_fxn_s!(Set2DRAB,assign_2d_range_all_b,bool);
1749impl_all_fxn_v!(Set2DRAVB,assign_2d_range_all_vb,bool);
1750
1751macro_rules! matrix_assign_range_all_fxn {
1752  ($op_fxn_name:tt, $fxn_name:ident) => {
1753    paste::paste! {
1754      fn $op_fxn_name(sink: Value, source: Value, ixes: Vec<Value>) -> MResult<Box<dyn MechFunction>> {
1755        let arg = (sink.clone(), ixes.as_slice(), source.clone());
1756                     impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, u8, "u8")
1757        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, u16, "u16"))
1758        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, u32, "u32"))
1759        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, u64, "u64"))
1760        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, u128, "u128"))
1761        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, i8, "i8"))
1762        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, i16, "i16"))
1763        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, i32, "i32"))
1764        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, i64, "i64"))
1765        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, f32, "f32"))
1766        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, f64, "f64"))
1767        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, R64, "rational"))
1768        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, C64, "complex"))
1769        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, bool, "bool"))
1770        .or_else(|_| impl_assign_fxn!(impl_set_range_all_arms, $fxn_name, arg, String, "string"))
1771
1772        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, u8,  "u8"))
1773        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, u16, "u16"))
1774        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, u32, "u32"))
1775        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, u64, "u64"))
1776        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, u128,"u128"))
1777        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, i8,  "i8"))
1778        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, i16, "i16"))
1779        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, i32, "i32"))
1780        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, i64, "i64"))
1781        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, i128,"i128"))
1782        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, f32, "f32"))
1783        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, f64, "f64"))
1784        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, R64, "rational"))
1785        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, C64, "complex"))
1786        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, bool, "bool"))
1787        .or_else(|_| impl_set_range_all_arms_b!($fxn_name, &arg, String, "string"))
1788        .map_err(|_| MechError2::new(
1789            UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "matrix/assign-range-all".to_string() },
1790            None
1791          ).with_compiler_loc()
1792        )
1793      }
1794    }
1795  }
1796}
1797
1798matrix_assign_range_all_fxn!(impl_assign_range_all_fxn, Set2DRA);
1799
1800pub struct MatrixAssignRangeAll {}
1801impl NativeFunctionCompiler for MatrixAssignRangeAll {
1802  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
1803    if arguments.len() <= 1 {
1804      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
1805    }
1806    let sink: Value = arguments[0].clone();
1807    let source: Value = arguments[1].clone();
1808    let ixes = arguments.clone().split_off(2);
1809    match impl_assign_range_all_fxn(sink.clone(),source.clone(),ixes.clone()) {
1810      Ok(fxn) => Ok(fxn),
1811      Err(_) => {
1812        match (sink.clone(),ixes.clone(),source.clone()) {
1813          (Value::MutableReference(sink),ixes,Value::MutableReference(source)) => { impl_assign_range_all_fxn(sink.borrow().clone(),source.borrow().clone(),ixes.clone()) },
1814          (sink,ixes,Value::MutableReference(source)) => { impl_assign_range_all_fxn(sink.clone(),source.borrow().clone(),ixes.clone()) },
1815          (Value::MutableReference(sink),ixes,source) => { impl_assign_range_all_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) },
1816          x => Err(MechError2::new(
1817              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "matrix/assign-range-all".to_string() },
1818              None
1819            ).with_compiler_loc()
1820          ),
1821        }
1822      }
1823    }
1824  }
1825}