1#[macro_use]
2use crate::*;
3use num_traits::*;
4#[cfg(feature = "matrix")]
5use mech_core::matrix::Matrix;
6
7macro_rules! pow_op {
10 ($lhs:expr, $rhs:expr, $out:expr) => {
11 unsafe {
12 *$out = (&*$lhs).pow(*$rhs);
13 }
14 };
15}
16
17macro_rules! pow_vec_op {
18 ($lhs:expr, $rhs:expr, $out:expr) => {
19 unsafe {
20 for i in 0..(&*$lhs).len() {
21 (&mut *$out)[i] = (&*$lhs)[i].pow((&*$rhs)[i]);
22 }
23 }
24 };
25}
26
27macro_rules! pow_scalar_lhs_op {
28 ($lhs:expr, $rhs:expr, $out:expr) => {
29 unsafe {
30 for i in 0..(&*$lhs).len() {
31 (&mut *$out)[i] = (&*$lhs)[i].pow(*$rhs);
32 }
33 }
34 };
35}
36
37macro_rules! pow_scalar_rhs_op {
38 ($lhs:expr, $rhs:expr, $out:expr) => {
39 unsafe {
40 for i in 0..(&*$rhs).len() {
41 (&mut *$out)[i] = (*$lhs).pow((&*$rhs)[i]);
42 }
43 }
44 };
45}
46
47macro_rules! pow_mat_vec_op {
48 ($lhs:expr, $rhs:expr, $out:expr) => {
49 unsafe {
50 let mut out_deref = &mut (*$out);
51 let lhs_deref = &(*$lhs);
52 let rhs_deref = &(*$rhs);
53 for (mut col, lhs_col) in out_deref.column_iter_mut().zip(lhs_deref.column_iter()) {
54 for i in 0..col.len() {
55 col[i] = lhs_col[i].pow(rhs_deref[i]);
56 }
57 }
58 }
59 };}
60
61macro_rules! pow_vec_mat_op {
62 ($lhs:expr, $rhs:expr, $out:expr) => {
63 unsafe {
64 let mut out_deref = &mut (*$out);
65 let lhs_deref = &(*$lhs);
66 let rhs_deref = &(*$rhs);
67 for (mut col, rhs_col) in out_deref.column_iter_mut().zip(rhs_deref.column_iter()) {
68 for i in 0..col.len() {
69 col[i] = lhs_deref[i].pow(rhs_col[i]);
70 }
71 }
72 }
73 };}
74
75macro_rules! pow_mat_row_op {
76 ($lhs:expr, $rhs:expr, $out:expr) => {
77 unsafe {
78 let mut out_deref = &mut (*$out);
79 let lhs_deref = &(*$lhs);
80 let rhs_deref = &(*$rhs);
81 for (mut row, lhs_row) in out_deref.row_iter_mut().zip(lhs_deref.row_iter()) {
82 for i in 0..row.len() {
83 row[i] = lhs_row[i].pow(rhs_deref[i]);
84 }
85 }
86 }
87 };}
88
89macro_rules! pow_row_mat_op {
90 ($lhs:expr, $rhs:expr, $out:expr) => {
91 unsafe {
92 let mut out_deref = &mut (*$out);
93 let lhs_deref = &(*$lhs);
94 let rhs_deref = &(*$rhs);
95 for (mut row, rhs_row) in out_deref.row_iter_mut().zip(rhs_deref.row_iter()) {
96 for i in 0..row.len() {
97 row[i] = lhs_deref[i].pow(rhs_row[i]);
98 }
99 }
100 }
101 };}
102
103#[macro_export]
104macro_rules! impl_powop {
105($struct_name:ident, $arg1_type:ty, $arg2_type:ty, $out_type:ty, $op:ident, $feature_flag:expr) => {
106 #[derive(Debug)]
107 struct $struct_name<T> {
108 lhs: Ref<$arg1_type>,
109 rhs: Ref<$arg2_type>,
110 out: Ref<$out_type>,
111 }
112 impl<T> MechFunctionFactory for $struct_name<T>
113 where
114 T: Copy + Debug + Clone + Sync + Send + 'static +
115 PartialEq + PartialOrd +
116 Add<Output = T> + AddAssign +
117 Sub<Output = T> + SubAssign +
118 Mul<Output = T> + MulAssign +
119 Div<Output = T> + DivAssign +
120 Pow<T, Output = T> +
121 CompileConst + ConstElem + AsValueKind +
122 Zero + One,
123 Ref<$out_type>: ToValue
124 {
125 fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
126 match args {
127 FunctionArgs::Binary(out, arg1, arg2) => {
128 let lhs: Ref<$arg1_type> = unsafe { arg1.as_unchecked() }.clone();
129 let rhs: Ref<$arg2_type> = unsafe { arg2.as_unchecked() }.clone();
130 let out: Ref<$out_type> = unsafe { out.as_unchecked() }.clone();
131 Ok(Box::new(Self {lhs, rhs, out }))
132 },
133 _ => Err(MechError2::new(
134 IncorrectNumberOfArguments { expected: 2, found: 0 },
135 None
136 ).with_compiler_loc()
137 ),
138 }
139 }
140 }
141 impl<T> MechFunctionImpl for $struct_name<T>
142 where
143 T: Copy + Debug + Clone + Sync + Send + 'static +
144 PartialEq + PartialOrd +
145 Add<Output = T> + AddAssign +
146 Sub<Output = T> + SubAssign +
147 Mul<Output = T> + MulAssign +
148 Div<Output = T> + DivAssign +
149 Pow<T, Output = T> +
150 Zero + One,
151 Ref<$out_type>: ToValue
152 {
153 fn solve(&self) {
154 let lhs_ptr = self.lhs.as_ptr();
155 let rhs_ptr = self.rhs.as_ptr();
156 let out_ptr = self.out.as_mut_ptr();
157 $op!(lhs_ptr,rhs_ptr,out_ptr);
158 }
159 fn out(&self) -> Value { self.out.to_value() }
160 fn to_string(&self) -> String { format!("{:#?}", self) }
161 }
162 #[cfg(feature = "compiler")]
163 impl<T> MechFunctionCompiler for $struct_name<T>
164 where
165 T: CompileConst + ConstElem + AsValueKind
166 {
167 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
168 let name = format!("{}<{}>", stringify!($struct_name), T::as_value_kind());
169 compile_binop!(name, self.out, self.lhs, self.rhs, ctx, $feature_flag);
170 }
171 }};}
172
173#[macro_export]
174macro_rules! impl_math_fxns_pow {
175 ($lib:ident) => {
176 impl_fxns!($lib,T,T,impl_powop);
177 }}
178
179impl_math_fxns_pow!(Pow);
180
181#[cfg(all(feature = "rational", feature = "i32"))]
182#[derive(Debug)]
183pub struct PowRational {
184 pub lhs: Ref<R64>,
185 pub rhs: Ref<i32>,
186 pub out: Ref<R64>,
187}
188#[cfg(all(feature = "rational", feature = "i32"))]
189impl MechFunctionFactory for PowRational {
190 fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
191 match args {
192 FunctionArgs::Binary(out, arg1, arg2) => {
193 let lhs: Ref<R64> = unsafe { arg1.as_unchecked() }.clone();
194 let rhs: Ref<i32> = unsafe { arg2.as_unchecked() }.clone();
195 let out: Ref<R64> = unsafe { out.as_unchecked() }.clone();
196 Ok(Box::new(Self {lhs, rhs, out }))
197 },
198 _ => Err(MechError2::new(
199 IncorrectNumberOfArguments { expected: 2, found: 0 },
200 None
201 ).with_compiler_loc()
202 ),
203 }
204 }
205}
206#[cfg(all(feature = "rational", feature = "i32"))]
207impl MechFunctionImpl for PowRational {
208 fn solve(&self) {
209 let lhs_ptr = self.lhs.as_ptr();
210 let rhs_ptr = self.rhs.as_ptr();
211 let out_ptr = self.out.as_mut_ptr();
212 unsafe {
213 (*out_ptr).0 = (*lhs_ptr).0.pow((*rhs_ptr));
214 }
215 }
216 fn out(&self) -> Value { self.out.to_value() }
217 fn to_string(&self) -> String { format!("{:#?}", self) }
218}
219#[cfg(all(feature = "rational", feature = "i32", feature = "compiler"))]
220impl MechFunctionCompiler for PowRational
221{
222 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
223 let name = format!("PowRational<{}>", R64::as_value_kind());
224 compile_binop!(name, self.out, self.lhs, self.rhs, ctx, FeatureFlag::Builtin(FeatureKind::Pow) );
225 }
226}
227
228fn impl_pow_fxn(lhs_value: Value, rhs_value: Value) -> MResult<Box<dyn MechFunction>> {
229 match (&lhs_value, &rhs_value) {
230 #[cfg(all(feature = "rational", feature = "i32"))]
231 (Value::R64(lhs), Value::I32(rhs)) => {
232 return Ok(Box::new(PowRational {
233 lhs: lhs.clone(),
234 rhs: rhs.clone(),
235 out: Ref::new(R64::default()),
236 }));
237 },
238 _ => (),
239 }
240 impl_binop_match_arms!(
241 Pow,
242 register_fxn_descriptor_inner,
243 (lhs_value, rhs_value),
244 U8, u8, "u8";
245 U16, u16, "u16";
246 U32, u32, "u32";
247 F32, f32, "f32";
248 F64, f64, "f64";
249 )
250}
251
252impl_mech_binop_fxn!(MathPow,impl_pow_fxn,"math/pow");