mech_math/op_assign/
mul_assign.rs

1#[macro_use]
2use crate::*;
3use super::*;
4use num_traits::*;
5#[cfg(feature = "matrix")]
6use mech_core::matrix::Matrix;
7
8// Mul Assign -----------------------------------------------------------------
9
10#[macro_export]
11macro_rules! impl_mul_assign_match_arms {
12  ($fxn_name:ident,$macro_name:ident, $arg:expr) => {
13    paste!{
14      [<impl_set_ $macro_name _match_arms>]!(
15        $fxn_name,
16        $arg,
17        U8, "u8";
18        U16, "u16";
19        U32, "u32";
20        U64, "u64";
21        U128, "u128";
22        I8, "i8";
23        I16, "i16";
24        I32, "i32";
25        I64, "i64";
26        U128, "u128";
27        F32, "f32"; 
28        F64, "f64" ;
29        C64, "complex";
30        R64, "rational";
31      )
32    }
33  }
34}
35
36#[cfg(feature = "matrix")]
37macro_rules! impl_mul_assign_range_fxn_s {
38  ($struct_name:ident, $op:ident, $ix:ty) => {
39    impl_op_assign_range_fxn_s!($struct_name, $op, $ix);
40  }
41}
42
43#[cfg(feature = "matrix")]
44macro_rules! impl_mul_assign_range_fxn_v {
45  ($struct_name:ident, $op:ident, $ix:ty) => {
46    impl_op_assign_range_fxn_v!($struct_name, $op, $ix);
47  }
48}
49
50// x = 1 ----------------------------------------------------------------------
51
52impl_assign_scalar_scalar!(Mul, *=);
53impl_assign_vector_vector!(Mul, *=);
54impl_assign_vector_scalar!(Mul, *=);
55
56fn mul_assign_value_fxn(sink: Value, source: Value) -> MResult<Box<dyn MechFunction>> {
57  impl_op_assign_value_match_arms!(
58    Mul,
59    (sink, source),
60    U8,  "u8";
61    U16, "u16";
62    U32, "u32";
63    U64, "u64";
64    U128, "u128";
65    I8,  "i8";
66    I16, "i16";
67    I32, "i32";
68    I64, "i64";
69    U128, "u128";
70    F32, "f32";
71    F64, "f64";
72    R64, "rational";
73    C64, "complex";
74  )
75}
76
77pub struct MulAssignValue {}
78impl NativeFunctionCompiler for MulAssignValue {
79  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
80    if arguments.len() <= 1 {
81      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
82    }
83    let sink = arguments[0].clone();
84    let source = arguments[1].clone();
85    match mul_assign_value_fxn(sink.clone(),source.clone()) {
86      Ok(fxn) => Ok(fxn),
87      Err(_) => {
88        match (sink,source) {
89          (Value::MutableReference(sink),Value::MutableReference(source)) => { mul_assign_value_fxn(sink.borrow().clone(),source.borrow().clone()) },
90          (sink,Value::MutableReference(source)) => { mul_assign_value_fxn(sink.clone(),source.borrow().clone()) },
91          (Value::MutableReference(sink),source) => { mul_assign_value_fxn(sink.borrow().clone(),source.clone()) },
92          (arg1,arg2) => Err(MechError2::new(
93              UnhandledFunctionArgumentKind2 { arg: (arg1.kind(),arg2.kind()), fxn_name: "math/mul-assign".to_string() },
94              None
95            ).with_compiler_loc()
96          ),
97        }
98      }
99    }
100  }
101}
102
103// x[1..3] *= 1 ----------------------------------------------------------------
104
105macro_rules! mul_assign_1d_range {
106  ($source:expr, $ix:expr, $sink:expr) => {
107    unsafe { 
108      for i in 0..($ix).len() {
109        ($sink)[($ix)[i] - 1] *= ($source).clone();
110      }
111    }
112  };}
113
114macro_rules! mul_assign_1d_range_b {
115  ($source:expr, $ix:expr, $sink:expr) => {
116    unsafe { 
117      for i in 0..($ix).len() {
118        if $ix[i] == true {
119          ($sink)[i] *= ($source).clone();
120        }
121      }
122    }
123  };}  
124
125macro_rules! mul_assign_1d_range_vec {
126  ($source:expr, $ix:expr, $sink:expr) => {
127    unsafe { 
128      for i in 0..($ix).len() {
129        ($sink)[($ix)[i] - 1] *= ($source)[i].clone();
130      }
131    }
132  };}
133
134macro_rules! mul_assign_1d_range_vec_b {
135  ($source:expr, $ix:expr, $sink:expr) => {
136    unsafe { 
137      for i in 0..($ix).len() {
138        if $ix[i] == true {
139          ($sink)[i] *= ($source)[i].clone();
140        }
141      }
142    }
143  };}  
144
145
146#[cfg(feature = "matrix")]
147impl_mul_assign_range_fxn_s!(MulAssign1DRS, mul_assign_1d_range,usize);
148#[cfg(feature = "matrix")]
149impl_mul_assign_range_fxn_s!(MulAssign1DRB, mul_assign_1d_range_b,bool);
150#[cfg(feature = "matrix")]
151impl_mul_assign_range_fxn_v!(MulAssign1DRV, mul_assign_1d_range_vec,usize);
152#[cfg(feature = "matrix")]
153impl_mul_assign_range_fxn_v!(MulAssign1DRVB,mul_assign_1d_range_vec_b,bool);
154
155op_assign_range_fxn!(mul_assign_range_fxn, MulAssign1DR);
156
157pub struct MulAssignRange {}
158impl NativeFunctionCompiler for MulAssignRange {
159  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
160    if arguments.len() <= 1 {
161      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
162    }
163    let sink: Value = arguments[0].clone();
164    let source: Value = arguments[1].clone();
165    let ixes = arguments.clone().split_off(2);
166    match mul_assign_range_fxn(sink.clone(),source.clone(),ixes.clone()) {
167      Ok(fxn) => Ok(fxn),
168      Err(x) => {
169        match (&sink,&ixes,&source) {
170          (Value::MutableReference(sink),ixes,Value::MutableReference(source)) => { mul_assign_range_fxn(sink.borrow().clone(),source.borrow().clone(),ixes.clone()) },
171          (sink,ixes,Value::MutableReference(source)) => { mul_assign_range_fxn(sink.clone(),source.borrow().clone(),ixes.clone()) },
172          (Value::MutableReference(sink),ixes,source) => { mul_assign_range_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) },
173          x => Err(MechError2::new(
174              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "math/mul-assign/range".to_string() },
175              None
176            ).with_compiler_loc()
177          ),
178        }
179      }
180    }
181  }
182}
183
184register_descriptor! {
185  FunctionCompilerDescriptor {
186    name: "math/mul-assign/range",
187    ptr: &MulAssignRange{},
188  }
189}
190
191// x[1..3,:] *= 1 ------------------------------------------------------------------
192
193macro_rules! mul_assign_2d_vector_all {
194  ($source:expr, $ix:expr, $sink:expr) => {
195      for cix in 0..($sink).ncols() {
196        for rix in $ix.iter() {
197          ($sink).column_mut(cix)[rix - 1] *= ($source).clone();
198        }
199      }
200    };}
201
202macro_rules! mul_assign_2d_vector_all_b {
203  ($source:expr, $ix:expr, $sink:expr) => {
204    for cix in 0..($sink).ncols() {
205      for rix in 0..$ix.len() {
206        if $ix[rix] == true {
207          ($sink).column_mut(cix)[rix] *= ($source).clone();
208        }
209      }
210    }
211  };} 
212
213macro_rules! mul_assign_2d_vector_all_mat {
214  ($source:expr, $ix:expr, $sink:expr) => {
215    {
216      let nsrc = $source.nrows();
217      for (i, &rix) in $ix.iter().enumerate() {
218        let row_index = rix - 1;
219        let mut sink_row = $sink.row_mut(row_index);
220        let src_row = $source.row(i % nsrc); // wrap around!
221        for (dst, src) in sink_row.iter_mut().zip(src_row.iter()) {
222          *dst *= *src;
223        }
224      }
225    }
226  };
227}
228
229macro_rules! mul_assign_2d_vector_all_mat_b {
230  ($source:expr, $ix:expr, $sink:expr) => {
231    {
232      let mut src_i = 0;
233      for (i, rix) in (&$ix).iter().enumerate() {
234        if *rix == true {
235          let mut sink_row = ($sink).row_mut(i);
236          let src_row = ($source).row(src_i);
237          for (dst, src) in sink_row.iter_mut().zip(src_row.iter()) {
238            *dst *= *src;
239          }
240          src_i += 1;
241        }
242      }
243    }
244  };
245}
246
247#[cfg(feature = "matrix")]
248impl_mul_assign_range_fxn_s!(MulAssign2DRAS, mul_assign_2d_vector_all,usize);
249#[cfg(feature = "matrix")]
250impl_mul_assign_range_fxn_s!(MulAssign2DRASB,mul_assign_2d_vector_all_b,bool);
251#[cfg(feature = "matrix")]
252impl_mul_assign_range_fxn_v!(MulAssign2DRAV, mul_assign_2d_vector_all_mat,usize);
253#[cfg(feature = "matrix")]
254impl_mul_assign_range_fxn_v!(MulAssign2DRAVB,mul_assign_2d_vector_all_mat_b,bool);
255
256op_assign_range_all_fxn!(mul_assign_range_all_fxn, MulAssign2DRA);
257
258pub struct MulAssignRangeAll {}
259impl NativeFunctionCompiler for MulAssignRangeAll {
260  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
261    if arguments.len() <= 1 {
262      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
263    }
264    let sink: Value = arguments[0].clone();
265    let source: Value = arguments[1].clone();
266    let ixes = arguments.clone().split_off(2);
267    match mul_assign_range_all_fxn(sink.clone(),source.clone(),ixes.clone()) {
268      Ok(fxn) => Ok(fxn),
269      Err(_) => {
270        match (&sink,&ixes,&source) {
271          (Value::MutableReference(sink),ixes,Value::MutableReference(source)) => { mul_assign_range_all_fxn(sink.borrow().clone(),source.borrow().clone(),ixes.clone()) },
272          (sink,ixes,Value::MutableReference(source)) => { mul_assign_range_all_fxn(sink.clone(),source.borrow().clone(),ixes.clone()) },
273          (Value::MutableReference(sink),ixes,source) => { mul_assign_range_all_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) },
274          x => Err(MechError2::new(
275              //UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "math/mul-assign/range-all".to_string() },
276              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|x| x.kind()).collect(), source.kind()), fxn_name: "math/mul-assign/range-all".to_string() },
277              None
278            ).with_compiler_loc()
279          ),
280        }
281      }
282    }
283  }
284}
285
286register_descriptor! {
287  FunctionCompilerDescriptor {
288    name: "math/mul-assign/range-all",
289    ptr: &MulAssignRangeAll{},
290  }
291}