mech_math/op_assign/
sub_assign.rs

1#[macro_use]
2use crate::*;
3use super::*;
4use num_traits::*;
5#[cfg(feature = "matrix")]
6use mech_core::matrix::Matrix;
7
8// Sub Assign -----------------------------------------------------------------
9
10#[macro_export]
11macro_rules! impl_sub_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_sub_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_sub_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!(Sub, -=);
53impl_assign_vector_vector!(Sub, -=);
54impl_assign_vector_scalar!(Sub, -=);
55
56fn sub_assign_value_fxn(sink: Value, source: Value) -> MResult<Box<dyn MechFunction>> {
57  impl_op_assign_value_match_arms!(
58    Sub,
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 SubAssignValue {}
78impl NativeFunctionCompiler for SubAssignValue {
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 sub_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)) => { sub_assign_value_fxn(sink.borrow().clone(),source.borrow().clone()) },
90          (sink,Value::MutableReference(source)) => { sub_assign_value_fxn(sink.clone(),source.borrow().clone()) },
91          (Value::MutableReference(sink),source) => { sub_assign_value_fxn(sink.borrow().clone(),source.clone()) },
92          (arg1,arg2) => Err(MechError2::new(
93              UnhandledFunctionArgumentKind2 { arg: (arg1.kind(),arg2.kind()), fxn_name: "math/sub-assign".to_string() },
94              None
95            ).with_compiler_loc()
96          ),
97        }
98      }
99    }
100  }
101}
102
103register_descriptor! {
104  FunctionCompilerDescriptor {
105    name: "math/sub-assign",
106    ptr: &SubAssignValue{},
107  }
108}
109
110// x[1..3] -= 1 ----------------------------------------------------------------
111
112macro_rules! sub_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! sub_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! sub_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! sub_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
153#[cfg(feature = "matrix")]
154impl_sub_assign_range_fxn_s!(SubAssign1DRS, sub_assign_1d_range,usize);
155#[cfg(feature = "matrix")]
156impl_sub_assign_range_fxn_s!(SubAssign1DRB, sub_assign_1d_range_b,bool);
157#[cfg(feature = "matrix")]
158impl_sub_assign_range_fxn_v!(SubAssign1DRV, sub_assign_1d_range_vec,usize);
159#[cfg(feature = "matrix")]
160impl_sub_assign_range_fxn_v!(SubAssign1DRVB,sub_assign_1d_range_vec_b,bool);
161
162op_assign_range_fxn!(sub_assign_range_fxn, SubAssign1DR);
163
164pub struct SubAssignRange {}
165impl NativeFunctionCompiler for SubAssignRange {
166  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
167    if arguments.len() <= 1 {
168      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
169    }
170    let sink: Value = arguments[0].clone();
171    let source: Value = arguments[1].clone();
172    let ixes = arguments.clone().split_off(2);
173    match sub_assign_range_fxn(sink.clone(),source.clone(),ixes.clone()) {
174      Ok(fxn) => Ok(fxn),
175      Err(x) => {
176        match (&sink,&ixes,&source) {
177          (Value::MutableReference(sink),ixes,Value::MutableReference(source)) => { sub_assign_range_fxn(sink.borrow().clone(),source.borrow().clone(),ixes.clone()) },
178          (sink,ixes,Value::MutableReference(source)) => { sub_assign_range_fxn(sink.clone(),source.borrow().clone(),ixes.clone()) },
179          (Value::MutableReference(sink),ixes,source) => { sub_assign_range_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) },
180          x => Err(MechError2::new(
181              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "math/sub-assign/range".to_string() },
182              None
183            ).with_compiler_loc()
184          ),
185        }
186      }
187    }
188  }
189}
190
191register_descriptor! {
192  FunctionCompilerDescriptor {
193    name: "math/sub-assign/range",
194    ptr: &SubAssignRange{},
195  }
196}
197
198// x[1..3,:] -= 1 ------------------------------------------------------------------
199
200macro_rules! sub_assign_2d_vector_all {
201  ($source:expr, $ix:expr, $sink:expr) => {
202      for cix in 0..($sink).ncols() {
203        for rix in $ix.iter() {
204          ($sink).column_mut(cix)[rix - 1] -= ($source).clone();
205        }
206      }
207    };}
208
209macro_rules! sub_assign_2d_vector_all_b {
210  ($source:expr, $ix:expr, $sink:expr) => {
211    for cix in 0..($sink).ncols() {
212      for rix in 0..$ix.len() {
213        if $ix[rix] == true {
214          ($sink).column_mut(cix)[rix] -= ($source).clone();
215        }
216      }
217    }
218  };} 
219
220macro_rules! sub_assign_2d_vector_all_mat {
221  ($source:expr, $ix:expr, $sink:expr) => {
222    {
223      let nsrc = $source.nrows();
224      for (i, &rix) in $ix.iter().enumerate() {
225        let row_index = rix - 1;
226        let mut sink_row = $sink.row_mut(row_index);
227        let src_row = $source.row(i % nsrc); // wrap around!
228        for (dst, src) in sink_row.iter_mut().zip(src_row.iter()) {
229          *dst -= *src;
230        }
231      }
232    }
233  };}
234
235macro_rules! sub_assign_2d_vector_all_mat_b {
236  ($source:expr, $ix:expr, $sink:expr) => {
237    {
238      let mut src_i = 0;
239      for (i, rix) in (&$ix).iter().enumerate() {
240        if *rix == true {
241          let mut sink_row = ($sink).row_mut(i);
242          let src_row = ($source).row(src_i);
243          for (dst, src) in sink_row.iter_mut().zip(src_row.iter()) {
244            *dst -= *src;
245          }
246          src_i += 1;
247        }
248      }
249    }
250  };}
251
252#[cfg(feature = "matrix")]
253impl_sub_assign_range_fxn_s!(SubAssign2DRAS, sub_assign_2d_vector_all,usize);
254#[cfg(feature = "matrix")]
255impl_sub_assign_range_fxn_s!(SubAssign2DRASB,sub_assign_2d_vector_all_b,bool);
256#[cfg(feature = "matrix")]
257impl_sub_assign_range_fxn_v!(SubAssign2DRAV, sub_assign_2d_vector_all_mat,usize);
258#[cfg(feature = "matrix")]
259impl_sub_assign_range_fxn_v!(SubAssign2DRAVB,sub_assign_2d_vector_all_mat_b,bool);
260
261op_assign_range_all_fxn!(sub_assign_range_all_fxn, SubAssign2DRA);
262
263pub struct SubAssignRangeAll {}
264impl NativeFunctionCompiler for SubAssignRangeAll {
265  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
266    if arguments.len() <= 1 {
267      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
268    }
269    let sink: Value = arguments[0].clone();
270    let source: Value = arguments[1].clone();
271    let ixes = arguments.clone().split_off(2);
272    match sub_assign_range_all_fxn(sink.clone(),source.clone(),ixes.clone()) {
273      Ok(fxn) => Ok(fxn),
274      Err(_) => {
275        match (&sink,&ixes,&source) {
276          (Value::MutableReference(sink),ixes,Value::MutableReference(source)) => { sub_assign_range_all_fxn(sink.borrow().clone(),source.borrow().clone(),ixes.clone()) },
277          (sink,ixes,Value::MutableReference(source)) => { sub_assign_range_all_fxn(sink.clone(),source.borrow().clone(),ixes.clone()) },
278          (Value::MutableReference(sink),ixes,source) => { sub_assign_range_all_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) },
279          x => Err(MechError2::new(
280              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|v| v.kind()).collect::<Vec<_>>(), source.kind()), fxn_name: "math/sub-assign/range-all".to_string() },
281              None
282            ).with_compiler_loc()
283          ),
284        }
285      }
286    }
287  }
288}
289
290register_descriptor! {
291  FunctionCompilerDescriptor {
292    name: "math/sub-assign/range-all",
293    ptr: &SubAssignRangeAll{},
294  }
295}