mech_math/op_assign/
add_assign.rs

1#[macro_use]
2use crate::*;
3use super::*;
4use num_traits::*;
5#[cfg(feature = "matrix")]
6use mech_core::matrix::Matrix;
7
8// Add Assign -----------------------------------------------------------------
9
10#[macro_export]
11macro_rules! impl_add_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_add_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_add_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!(Add, +=);
53impl_assign_vector_vector!(Add, +=);
54impl_assign_vector_scalar!(Add, +=);
55
56pub fn add_assign_math_fxn(sink: Value, source: Value) -> MResult<Box<dyn MechFunction>> {
57  impl_op_assign_value_match_arms!(
58    Add,
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 AddAssignMath {}
78impl NativeFunctionCompiler for AddAssignMath {
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 add_assign_math_fxn(sink.clone(),source.clone()) {
86      Ok(fxn) => Ok(fxn),
87      Err(x) => {
88        match (sink,source) {
89          (Value::MutableReference(sink),Value::MutableReference(source)) => { add_assign_math_fxn(sink.borrow().clone(),source.borrow().clone()) },
90          (sink,Value::MutableReference(source)) => { add_assign_math_fxn(sink.clone(),source.borrow().clone()) },
91          (Value::MutableReference(sink),source) => { add_assign_math_fxn(sink.borrow().clone(),source.clone()) },
92          (arg1,arg2) => Err(MechError2::new(
93              UnhandledFunctionArgumentKind2 { arg: (arg1.kind(),arg2.kind()), fxn_name: "math/add-assign".to_string() },
94              None
95            ).with_compiler_loc()
96          ),
97        }
98      }
99    }
100  }
101}
102
103register_descriptor! {
104  FunctionCompilerDescriptor {
105    name: "math/add-assign",
106    ptr: &AddAssignMath{},
107  }
108}
109
110// x[1..3] += 1 ----------------------------------------------------------------
111
112macro_rules! add_assign_1d_range {
113  ($source:expr, $ix:expr, $sink:expr) => {
114    unsafe { 
115      for i in 0..($ix).len() {
116        ($sink)[($ix)[i] - 1] += ($source).clone();
117      }
118    }
119  };}
120
121macro_rules! add_assign_1d_range_b {
122  ($source:expr, $ix:expr, $sink:expr) => {
123    unsafe { 
124      for i in 0..($ix).len() {
125        if $ix[i] == true {
126          ($sink)[i] += ($source).clone();
127        }
128      }
129    }
130  };}  
131
132macro_rules! add_assign_1d_range_vec {
133  ($source:expr, $ix:expr, $sink:expr) => {
134    unsafe { 
135      for i in 0..($ix).len() {
136        ($sink)[($ix)[i] - 1] += ($source)[i].clone();
137      }
138    }
139  };}
140
141macro_rules! add_assign_1d_range_vec_b {
142  ($source:expr, $ix:expr, $sink:expr) => {
143    unsafe { 
144      for i in 0..($ix).len() {
145        if $ix[i] == true {
146          ($sink)[i] += ($source)[i].clone();
147        }
148      }
149    }
150  };}
151
152#[cfg(feature = "matrix")]
153impl_add_assign_range_fxn_s!(AddAssign1DRS,add_assign_1d_range,usize);
154#[cfg(feature = "matrix")]
155impl_add_assign_range_fxn_s!(AddAssign1DRB,add_assign_1d_range_b,bool);
156#[cfg(feature = "matrix")]
157impl_add_assign_range_fxn_v!(AddAssign1DRV,add_assign_1d_range_vec,usize);
158#[cfg(feature = "matrix")]
159impl_add_assign_range_fxn_v!(AddAssign1DRVB,add_assign_1d_range_vec_b,bool);
160
161op_assign_range_fxn!(add_assign_range_fxn, AddAssign1DR);
162
163pub struct AddAssignRange {}
164impl NativeFunctionCompiler for AddAssignRange {
165  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
166    if arguments.len() <= 1 {
167      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
168    }
169    let sink: Value = arguments[0].clone();
170    let source: Value = arguments[1].clone();
171    let ixes = arguments.clone().split_off(2);
172    match add_assign_range_fxn(sink.clone(),source.clone(),ixes.clone()) {
173      Ok(fxn) => Ok(fxn),
174      Err(x) => {
175        match (&sink,&ixes,&source) {
176          (Value::MutableReference(sink),ixes,Value::MutableReference(source)) => { add_assign_range_fxn(sink.borrow().clone(),source.borrow().clone(),ixes.clone()) },
177          (sink,ixes,Value::MutableReference(source)) => { add_assign_range_fxn(sink.clone(),source.borrow().clone(),ixes.clone()) },
178          (Value::MutableReference(sink),ixes,source) => { add_assign_range_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) },
179          (sink, ixes, source) => Err(MechError2::new(
180              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|x| x.kind()).collect(), source.kind()), fxn_name: "math/add-assign/range".to_string() },
181              None
182            ).with_compiler_loc()
183          ),
184        }
185      }
186    }
187  }
188}
189
190register_descriptor! {
191  FunctionCompilerDescriptor {
192    name: "math/add-assign/range",
193    ptr: &AddAssignRange{},
194  }
195}
196
197// x[1..3,:] += 1 ------------------------------------------------------------------
198
199macro_rules! add_assign_2d_vector_all {
200  ($source:expr, $ix:expr, $sink:expr) => {
201      for cix in 0..($sink).ncols() {
202        for rix in $ix.iter() {
203          ($sink).column_mut(cix)[rix - 1] += ($source).clone();
204        }
205      }
206    };}
207
208macro_rules! add_assign_2d_vector_all_b {
209  ($source:expr, $ix:expr, $sink:expr) => {
210    for cix in 0..($sink).ncols() {
211      for rix in 0..$ix.len() {
212        if $ix[rix] == true {
213          ($sink).column_mut(cix)[rix] += ($source).clone();
214        }
215      }
216    }
217  };} 
218
219macro_rules! add_assign_2d_vector_all_mat {
220  ($source:expr, $ix:expr, $sink:expr) => {
221    {
222      let nsrc = $source.nrows();
223      for (i, &rix) in $ix.iter().enumerate() {
224        let row_index = rix - 1;
225        let mut sink_row = $sink.row_mut(row_index);
226        let src_row = $source.row(i % nsrc); // wrap around!
227        for (dst, src) in sink_row.iter_mut().zip(src_row.iter()) {
228          *dst += *src;
229        }
230      }
231    }
232  };}
233
234macro_rules! add_assign_2d_vector_all_mat_b {
235  ($source:expr, $ix:expr, $sink:expr) => {
236    {
237      let mut src_i = 0;
238      for (i, rix) in (&$ix).iter().enumerate() {
239        if *rix == true {
240          let mut sink_row = ($sink).row_mut(i);
241          let src_row = ($source).row(src_i);
242          for (dst, src) in sink_row.iter_mut().zip(src_row.iter()) {
243            *dst += *src;
244          }
245          src_i += 1;
246        }
247      }
248    }
249  };}
250
251#[cfg(feature = "matrix")]
252impl_add_assign_range_fxn_s!(AddAssign2DRAS, add_assign_2d_vector_all,usize);
253#[cfg(feature = "matrix")]
254impl_add_assign_range_fxn_s!(AddAssign2DRASB,add_assign_2d_vector_all_b,bool);
255#[cfg(feature = "matrix")]
256impl_add_assign_range_fxn_v!(AddAssign2DRAV, add_assign_2d_vector_all_mat,usize);
257#[cfg(feature = "matrix")]
258impl_add_assign_range_fxn_v!(AddAssign2DRAVB,add_assign_2d_vector_all_mat_b,bool);
259
260op_assign_range_all_fxn!(add_assign_range_all_fxn, AddAssign2DRA);
261
262pub struct AddAssignRangeAll {}
263impl NativeFunctionCompiler for AddAssignRangeAll {
264  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
265    if arguments.len() <= 1 {
266      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
267    }
268    let sink: Value = arguments[0].clone();
269    let source: Value = arguments[1].clone();
270    let ixes = arguments.clone().split_off(2);
271    match add_assign_range_all_fxn(sink.clone(),source.clone(),ixes.clone()) {
272      Ok(fxn) => Ok(fxn),
273      Err(_) => {
274        match (sink,ixes,source) {
275          (Value::MutableReference(sink),ixes,Value::MutableReference(source)) => { add_assign_range_all_fxn(sink.borrow().clone(),source.borrow().clone(),ixes.clone()) },
276          (sink,ixes,Value::MutableReference(source)) => { add_assign_range_all_fxn(sink.clone(),source.borrow().clone(),ixes.clone()) },
277          (Value::MutableReference(sink),ixes,source) => { add_assign_range_all_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) },
278          (sink, ixes, source) => Err(MechError2::new(
279              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|x| x.kind()).collect(), source.kind()), fxn_name: "math/add-assign/range-all".to_string() },
280              None
281            ).with_compiler_loc()
282          ),
283        }
284      }
285    }
286  }
287}
288
289register_descriptor! {
290  FunctionCompilerDescriptor {
291    name: "math/add-assign/range-all",
292    ptr: &AddAssignRangeAll{},
293  }
294}