mech_math/ops/
pow.rs

1#[macro_use]
2use crate::*;
3use num_traits::*;
4#[cfg(feature = "matrix")]
5use mech_core::matrix::Matrix;
6
7// Pow ------------------------------------------------------------------------
8
9macro_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");