mech_math/op_assign/
div_assign.rs

1#[macro_use]
2use crate::*;
3use super::*;
4use num_traits::*;
5#[cfg(feature = "matrix")]
6use mech_core::matrix::Matrix;
7use std::ops::DivAssign;
8
9// Div Assign -----------------------------------------------------------------
10
11// We will mostly use the assign macros for this
12
13#[macro_export]
14macro_rules! impl_div_assign_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        U8, "u8";
21        U16, "u16";
22        U32, "u32";
23        U64, "u64";
24        U128, "u128";
25        I8, "i8";
26        I16, "i16";
27        I32, "i32";
28        I64, "i64";
29        U128, "u128";
30        F32, "f32"; 
31        F64, "f64" ;
32        C64, "complex";
33        R64, "rational";
34      )
35    }
36  }
37}
38
39#[cfg(feature = "matrix")]
40macro_rules! impl_div_assign_range_fxn_s {
41  ($struct_name:ident, $op:ident, $ix:ty) => {
42    impl_op_assign_range_fxn_s!($struct_name, $op, $ix);
43  }
44}
45
46#[cfg(feature = "matrix")]
47macro_rules! impl_div_assign_range_fxn_v {
48  ($struct_name:ident, $op:ident, $ix:ty) => {
49    impl_op_assign_range_fxn_v!($struct_name, $op, $ix);
50  }
51}
52
53// x /= 1 ----------------------------------------------------------------------
54
55impl_assign_scalar_scalar!(Div, /=);
56impl_assign_vector_vector!(Div, /=);
57impl_assign_vector_scalar!(Div, /=);
58fn div_assign_value_fxn(sink: Value, source: Value) -> MResult<Box<dyn MechFunction>> {
59  impl_op_assign_value_match_arms!(
60    Div,
61    (sink, source),
62    U8,  "u8";
63    U16, "u16";
64    U32, "u32";
65    U64, "u64";
66    U128, "u128";
67    I8,  "i8";
68    I16, "i16";
69    I32, "i32";
70    I64, "i64";
71    U128, "u128";
72    F32, "f32";
73    F64, "f64";
74    R64, "rational";
75    C64, "complex";
76  )
77}
78
79pub struct DivAssignValue {}
80impl NativeFunctionCompiler for DivAssignValue {
81  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
82    if arguments.len() <= 1 {
83      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
84    }
85    let sink = arguments[0].clone();
86    let source = arguments[1].clone();
87    match div_assign_value_fxn(sink.clone(),source.clone()) {
88      Ok(fxn) => Ok(fxn),
89      Err(x) => {
90        match (sink,source) {
91          (Value::MutableReference(sink),Value::MutableReference(source)) => { div_assign_value_fxn(sink.borrow().clone(),source.borrow().clone()) },
92          (sink,Value::MutableReference(source)) => { div_assign_value_fxn(sink.clone(),source.borrow().clone()) },
93          (Value::MutableReference(sink),source) => { div_assign_value_fxn(sink.borrow().clone(),source.clone()) },
94          (arg1,arg2) => Err(MechError2::new(
95              UnhandledFunctionArgumentKind2 { arg: (arg1.kind(),arg2.kind()), fxn_name: "math/div-assign".to_string() },
96              None
97            ).with_compiler_loc()
98          ),
99        }
100      }
101    }
102  }
103}
104
105register_descriptor! {
106  FunctionCompilerDescriptor {
107    name: "math/div-assign",
108    ptr: &DivAssignValue{},
109  }
110}
111
112// x[1..3] /= 1 ----------------------------------------------------------------
113
114macro_rules! div_assign_1d_range {
115  ($source:expr, $ix:expr, $sink:expr) => {
116    unsafe { 
117      for i in 0..($ix).len() {
118        ($sink)[($ix)[i] - 1] /= *($source);
119      }
120    }
121  };}
122
123macro_rules! div_assign_1d_range_b {
124  ($source:expr, $ix:expr, $sink:expr) => {
125    unsafe { 
126      for i in 0..($ix).len() {
127        if $ix[i] == true {
128          ($sink)[i] /= *($source);
129        }
130      }
131    }
132  };}  
133
134macro_rules! div_assign_1d_range_vec {
135  ($source:expr, $ix:expr, $sink:expr) => {
136    unsafe { 
137      for i in 0..($ix).len() {
138        ($sink)[($ix)[i] - 1] /= ($source)[i];
139      }
140    }
141  };}
142
143macro_rules! div_assign_1d_range_vec_b {
144  ($source:expr, $ix:expr, $sink:expr) => {
145    unsafe { 
146      for i in 0..($ix).len() {
147        if $ix[i] == true {
148          ($sink)[i] /= ($source)[i];
149        }
150      }
151    }
152  };}
153
154#[cfg(feature = "matrix")]
155impl_div_assign_range_fxn_s!(DivAssign1DRS,div_assign_1d_range,usize);
156#[cfg(feature = "matrix")]
157impl_div_assign_range_fxn_s!(DivAssign1DRB,div_assign_1d_range_b,bool);
158#[cfg(feature = "matrix")]
159impl_div_assign_range_fxn_v!(DivAssign1DRV,div_assign_1d_range_vec,usize);
160#[cfg(feature = "matrix")]
161impl_div_assign_range_fxn_v!(DivAssign1DRVB,div_assign_1d_range_vec_b,bool);
162
163op_assign_range_fxn!(div_assign_range_fxn, DivAssign1DR);
164
165pub struct DivAssignRange {}
166impl NativeFunctionCompiler for DivAssignRange {
167  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
168    if arguments.len() <= 1 {
169      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
170    }
171    let sink: Value = arguments[0].clone();
172    let source: Value = arguments[1].clone();
173    let ixes = arguments.clone().split_off(2);
174    match div_assign_range_fxn(sink.clone(),source.clone(),ixes.clone()) {
175      Ok(fxn) => Ok(fxn),
176      Err(x) => {
177        match (&sink, &ixes, &source) {
178          (Value::MutableReference(sink),ixes,Value::MutableReference(source)) => { div_assign_range_fxn(sink.borrow().clone(),source.borrow().clone(),ixes.clone()) },
179          (sink,ixes,Value::MutableReference(source)) => { div_assign_range_fxn(sink.clone(),source.borrow().clone(),ixes.clone()) },
180          (Value::MutableReference(sink),ixes,source) => { div_assign_range_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) },
181          x => Err(MechError2::new(
182              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|x| x.kind()).collect(), source.kind()), fxn_name: "math/div-assign/range".to_string() },
183              None
184            ).with_compiler_loc()
185          ),
186        }
187      }
188    }
189  }
190}
191
192register_descriptor! {
193  FunctionCompilerDescriptor {
194    name: "math/div-assign/range",
195    ptr: &DivAssignRange{},
196  }
197}
198
199// x[1..3,:] /= 1 ------------------------------------------------------------------
200
201
202macro_rules! div_assign_2d_vector_all {
203  ($source:expr, $ix:expr, $sink:expr) => {
204    for val in ($sink).iter_mut() {
205      *val /= (*$source);
206    }
207  };}
208
209macro_rules! div_assign_2d_vector_all_b {
210  ($source:expr, $ix:expr, $sink:expr) => {
211    let ncols = ($sink).ncols();
212    for (i, val) in ($sink).iter_mut().enumerate() {
213      let row = i / ncols;
214      if $ix[row] {
215        *val /= *($source);
216      }
217    }
218  };}
219
220macro_rules! div_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! div_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_div_assign_range_fxn_s!(DivAssign2DRAS,div_assign_2d_vector_all,usize);
254#[cfg(feature = "matrix")]
255impl_div_assign_range_fxn_s!(DivAssign2DRASB,div_assign_2d_vector_all_b,bool);
256#[cfg(feature = "matrix")]
257impl_div_assign_range_fxn_v!(DivAssign2DRAV,div_assign_2d_vector_all_mat,usize);
258#[cfg(feature = "matrix")]
259impl_div_assign_range_fxn_v!(DivAssign2DRAVB,div_assign_2d_vector_all_mat_b,bool);
260
261op_assign_range_all_fxn!(div_assign_range_all_fxn, DivAssign2DRA);
262
263pub struct DivAssignRangeAll {}
264impl NativeFunctionCompiler for DivAssignRangeAll {
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 div_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)) => { div_assign_range_all_fxn(sink.borrow().clone(),source.borrow().clone(),ixes.clone()) },
277          (sink,ixes,Value::MutableReference(source)) => { div_assign_range_all_fxn(sink.clone(),source.borrow().clone(),ixes.clone()) },
278          (Value::MutableReference(sink),ixes,source) => { div_assign_range_all_fxn(sink.borrow().clone(),source.clone(),ixes.clone()) },
279          _ => Err(MechError2::new(
280              UnhandledFunctionArgumentIxes { arg: (sink.kind(), ixes.iter().map(|x| x.kind()).collect(), source.kind()), fxn_name: "math/div-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/div-assign/range-all",
293    ptr: &DivAssignRangeAll{},
294  }
295}