1#[macro_use]
2use crate::*;
3use num_traits::*;
4#[cfg(feature = "matrix")]
5use mech_core::matrix::Matrix;
6
7#[macro_export]
10macro_rules! impl_binop2 {
11 ($struct_name:ident, $arg1_type:ty, $arg2_type:ty, $out_type:ty, $op:ident, $feature_flag:expr) => {
12 #[derive(Debug)]
13 struct $struct_name<T> {
14 lhs: Ref<$arg1_type>,
15 rhs: Ref<$arg2_type>,
16 out: Ref<$out_type>,
17 }
18 impl<T> MechFunctionFactory for $struct_name<T>
19 where
20 T: Copy + Debug + Clone + Sync + Send + 'static +
21 PartialEq + PartialOrd + CompileConst + ConstElem +
22 Add<Output = T> + AddAssign +
23 Sub<Output = T> + SubAssign +
24 Mul<Output = T> + MulAssign +
25 Div<Output = T> + DivAssign +
26 Rem<Output = T> + RemAssign +
27 Zero + One + AsValueKind,
28 Ref<$out_type>: ToValue
29 {
30 fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
31 match args {
32 FunctionArgs::Binary(out, arg1, arg2) => {
33 let lhs: Ref<$arg1_type> = unsafe { arg1.as_unchecked() }.clone();
34 let rhs: Ref<$arg2_type> = unsafe { arg2.as_unchecked() }.clone();
35 let out: Ref<$out_type> = unsafe { out.as_unchecked() }.clone();
36 Ok(Box::new(Self {lhs, rhs, out }))
37 },
38 _ => Err(MechError2::new(
39 IncorrectNumberOfArguments { expected: 2, found: 0 },
40 None
41 ).with_compiler_loc()
42 ),
43 }
44 }
45 }
46 impl<T> MechFunctionImpl for $struct_name<T>
47 where
48 T: Copy + Debug + Clone + Sync + Send + 'static +
49 PartialEq + PartialOrd +
50 Add<Output = T> + AddAssign +
51 Sub<Output = T> + SubAssign +
52 Mul<Output = T> + MulAssign +
53 Div<Output = T> + DivAssign +
54 Rem<Output = T> + RemAssign +
55 Zero + One,
56 Ref<$out_type>: ToValue
57 {
58 fn solve(&self) {
59 let lhs_ptr = self.lhs.as_ptr();
60 let rhs_ptr = self.rhs.as_ptr();
61 let out_ptr = self.out.as_mut_ptr();
62 $op!(lhs_ptr,rhs_ptr,out_ptr);
63 }
64 fn out(&self) -> Value { self.out.to_value() }
65 fn to_string(&self) -> String { format!("{:#?}", self) }
66 }
67 #[cfg(feature = "compiler")]
68 impl<T> MechFunctionCompiler for $struct_name<T>
69 where
70 T: CompileConst + ConstElem + AsValueKind
71 {
72 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
73 let name = format!("{}<{}>", stringify!($struct_name), T::as_value_kind());
74 compile_binop!(name, self.out, self.lhs, self.rhs, ctx, $feature_flag);
75 }
76 }};
77}
78
79macro_rules! mod_op {
80 ($lhs:expr, $rhs:expr, $out:expr) => {
81 unsafe { *$out = *$lhs % *$rhs; }};}
82
83macro_rules! mod_vec_op {
84 ($lhs:expr, $rhs:expr, $out:expr) => {
85 unsafe {
86 let mut out_deref = &mut (*$out);
87 let lhs_deref = &(*$lhs);
88 let rhs_deref = &(*$rhs);
89 for (o,(l,r)) in out_deref.iter_mut().zip(lhs_deref.iter().zip(rhs_deref.iter())) {
90 *o = *l % *r;
91 }
92 }};}
93
94macro_rules! mod_scalar_lhs_op {
95 ($lhs:expr, $rhs:expr, $out:expr) => {
96 unsafe {
97 let mut out_deref = &mut (*$out);
98 let lhs_deref = &(*$lhs);
99 let rhs_deref = (*$rhs);
100 for (o,l) in out_deref.iter_mut().zip(lhs_deref.iter()) {
101 *o = *l % rhs_deref;
102 }
103 }};}
104
105macro_rules! mod_scalar_rhs_op {
106 ($lhs:expr, $rhs:expr, $out:expr) => {
107 unsafe {
108 let mut out_deref = &mut (*$out);
109 let lhs_deref = (*$lhs);
110 let rhs_deref = &(*$rhs);
111 for (o,r) in out_deref.iter_mut().zip(rhs_deref.iter()) {
112 *o = lhs_deref % *r;
113 }
114 }};}
115
116macro_rules! mod_mat_vec_op {
117 ($lhs:expr, $rhs:expr, $out:expr) => {
118 unsafe {
119 let mut out_deref = &mut (*$out);
120 let lhs_deref = &(*$lhs);
121 let rhs_deref = &(*$rhs);
122 for (mut col, lhs_col) in out_deref.column_iter_mut().zip(lhs_deref.column_iter()) {
123 for i in 0..col.len() {
124 col[i] = lhs_col[i] % rhs_deref[i];
125 }
126 }
127 }
128 };}
129
130macro_rules! mod_vec_mat_op {
131 ($lhs:expr, $rhs:expr, $out:expr) => {
132 unsafe {
133 let mut out_deref = &mut (*$out);
134 let lhs_deref = &(*$lhs);
135 let rhs_deref = &(*$rhs);
136 for (mut col, rhs_col) in out_deref.column_iter_mut().zip(rhs_deref.column_iter()) {
137 for i in 0..col.len() {
138 col[i] = lhs_deref[i] % rhs_col[i];
139 }
140 }
141 }
142 };}
143
144macro_rules! mod_mat_row_op {
145 ($lhs:expr, $rhs:expr, $out:expr) => {
146 unsafe {
147 let mut out_deref = &mut (*$out);
148 let lhs_deref = &(*$lhs);
149 let rhs_deref = &(*$rhs);
150 for (mut row, lhs_row) in out_deref.row_iter_mut().zip(lhs_deref.row_iter()) {
151 for i in 0..row.len() {
152 row[i] = lhs_row[i] % rhs_deref[i];
153 }
154 }
155 }
156 };}
157
158macro_rules! mod_row_mat_op {
159 ($lhs:expr, $rhs:expr, $out:expr) => {
160 unsafe {
161 let mut out_deref = &mut (*$out);
162 let lhs_deref = &(*$lhs);
163 let rhs_deref = &(*$rhs);
164 for (mut row, rhs_row) in out_deref.row_iter_mut().zip(rhs_deref.row_iter()) {
165 for i in 0..row.len() {
166 row[i] = lhs_deref[i] % rhs_row[i];
167 }
168 }
169 }
170 };}
171
172
173macro_rules! impl_math_fxns2 {
174 ($lib:ident) => {
175 impl_fxns!($lib,T,T,impl_binop2);
176 }}
177
178impl_math_fxns2!(Mod);
179
180fn impl_mod_fxn(lhs_value: Value, rhs_value: Value) -> MResult<Box<dyn MechFunction>> {
181 impl_binop_match_arms!(
182 Mod,
183 register_fxn_descriptor_inner,
184 (lhs_value, rhs_value),
185 I8, i8, "i8";
186 I16, i16, "i16";
187 I32, i32, "i32";
188 I64, i64, "i64";
189 I128, i128, "i128";
190 U8, u8, "u8";
191 U16, u16, "u16";
192 U32, u32, "u32";
193 U64, u64, "u64";
194 U128, u128, "u128";
195 F32, f32, "f32";
196 F64, f64, "f64";
197 )
198}
199
200impl_mech_binop_fxn!(MathMod,impl_mod_fxn,"math/mod");