1#[macro_use]
2use crate::*;
3use super::*;
4use num_traits::*;
5#[cfg(feature = "matrix")]
6use mech_core::matrix::Matrix;
7
8#[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
50impl_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
110macro_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
198macro_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); 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}