mech_math/
atan2.rs

1use crate::*;
2use mech_core::*;
3use libm::{atan2,atan2f};
4
5// Atan2 ------------------------------------------------------------------------
6
7macro_rules! atan2_op {
8  ($arg1:expr, $arg2:expr, $out:expr) => {
9    unsafe{(*$out).0 = atan2((*$arg1).0,(*$arg2).0);}
10  };}
11
12macro_rules! atan2_vec_op {
13  ($arg1:expr, $arg2:expr, $out:expr) => {
14    unsafe {
15      let arg1_deref = &(*$arg1);
16      let arg2_deref = &(*$arg2);
17      let mut out_deref = (&mut *$out);
18      for i in 0..arg1_deref.len() {
19        (out_deref[i]).0 = atan2(arg1_deref[i].0,arg2_deref[i].0);
20      }}};}
21
22macro_rules! atan2f_op {
23  ($arg1:expr, $arg2:expr, $out:expr) => {
24    unsafe{(*$out).0 = atan2f((*$arg1).0,(*$arg2).0);}
25  };}
26
27macro_rules! atan2f_vec_op {
28  ($arg1:expr, $arg2:expr, $out:expr) => {
29    unsafe {
30      let arg1_deref = &(*$arg1);
31      let arg2_deref = &(*$arg2);
32      let mut out_deref = (&mut *$out);
33      for i in 0..arg1_deref.len() {
34        (out_deref[i]).0 = atan2f(arg1_deref[i].0,arg2_deref[i].0);
35      }}};}
36
37macro_rules! impl_two_arg_fxn {
38  ($struct_name:ident, $kind1:ty, $kind2:ty, $out_kind:ty, $op:ident) => {
39    #[derive(Debug)]
40    struct $struct_name {
41      arg1: Ref<$kind1>,
42      arg2: Ref<$kind2>,
43      out: Ref<$out_kind>,
44    }
45    impl MechFunction for $struct_name {
46      fn solve(&self) {
47        let arg1_ptr = self.arg1.as_ptr();
48        let arg2_ptr = self.arg2.as_ptr();
49        let out_ptr = self.out.as_ptr();
50        $op!(arg1_ptr,arg2_ptr,out_ptr);
51      }
52      fn out(&self) -> Value { self.out.to_value() }
53      fn to_string(&self) -> String { format!("{:#?}", self) }
54    }};}
55
56impl_two_arg_fxn!(Atan2F32, F32, F32, F32, atan2f_op);
57#[cfg(feature = "Matrix1")]
58impl_two_arg_fxn!(Atan2M1F32, Matrix1<F32>, Matrix1<F32>, Matrix1<F32>, atan2f_vec_op);
59#[cfg(feature = "Matrix2")]
60impl_two_arg_fxn!(Atan2M2F32, Matrix2<F32>, Matrix2<F32>, Matrix2<F32>, atan2f_vec_op);
61#[cfg(feature = "Matrix3")]
62impl_two_arg_fxn!(Atan2M3F32, Matrix3<F32>, Matrix3<F32>, Matrix3<F32>, atan2f_vec_op);
63#[cfg(feature = "Matrix2x3")]
64impl_two_arg_fxn!(Atan2M2x3F32, Matrix2x3<F32>, Matrix2x3<F32>, Matrix2x3<F32>, atan2f_vec_op);
65#[cfg(feature = "Matrix3")]
66impl_two_arg_fxn!(Atan2M3x2F32, Matrix3x2<F32>, Matrix3x2<F32>, Matrix3x2<F32>, atan2f_vec_op);
67#[cfg(feature = "Matrix4")]
68impl_two_arg_fxn!(Atan2M4F32, Matrix4<F32>, Matrix4<F32>, Matrix4<F32>, atan2f_vec_op);
69#[cfg(feature = "Vector2")]
70impl_two_arg_fxn!(Atan2V2F32, Vector2<F32>, Vector2<F32>, Vector2<F32>, atan2f_vec_op);
71#[cfg(feature = "Vector3")]
72impl_two_arg_fxn!(Atan2V3F32, Vector3<F32>, Vector3<F32>, Vector3<F32>, atan2f_vec_op);
73#[cfg(feature = "Vector4")]
74impl_two_arg_fxn!(Atan2V4F32, Vector4<F32>, Vector4<F32>, Vector4<F32>, atan2f_vec_op);
75#[cfg(feature = "RowVector2")]
76impl_two_arg_fxn!(Atan2R2F32, RowVector2<F32>, RowVector2<F32>, RowVector2<F32>, atan2f_vec_op);
77#[cfg(feature = "RowVector3")]
78impl_two_arg_fxn!(Atan2R3F32, RowVector3<F32>, RowVector3<F32>, RowVector3<F32>, atan2f_vec_op);
79#[cfg(feature = "RowVector4")]
80impl_two_arg_fxn!(Atan2R4F32, RowVector4<F32>, RowVector4<F32>, RowVector4<F32>, atan2f_vec_op);
81#[cfg(feature = "RowVectorD")]
82impl_two_arg_fxn!(Atan2RDF32, RowDVector<F32>, RowDVector<F32>, RowDVector<F32>, atan2f_vec_op);
83#[cfg(feature = "VectorD")]
84impl_two_arg_fxn!(Atan2VDF32, DVector<F32>, DVector<F32>, DVector<F32>, atan2f_vec_op);
85#[cfg(feature = "MatrixD")]
86impl_two_arg_fxn!(Atan2MDF32, DMatrix<F32>, DMatrix<F32>, DMatrix<F32>, atan2f_vec_op);
87
88impl_two_arg_fxn!(Atan2F64, F64, F64, F64, atan2_op);
89#[cfg(feature = "Matrix1")]
90impl_two_arg_fxn!(Atan2M1F64, Matrix1<F64>, Matrix1<F64>, Matrix1<F64>, atan2_vec_op);
91#[cfg(feature = "Matrix2")]
92impl_two_arg_fxn!(Atan2M2F64, Matrix2<F64>, Matrix2<F64>, Matrix2<F64>, atan2_vec_op);
93#[cfg(feature = "Matrix3")]
94impl_two_arg_fxn!(Atan2M3F64, Matrix3<F64>, Matrix3<F64>, Matrix3<F64>, atan2_vec_op);
95#[cfg(feature = "Matrix2x3")]
96impl_two_arg_fxn!(Atan2M2x3F64, Matrix2x3<F64>, Matrix2x3<F64>, Matrix2x3<F64>, atan2_vec_op);
97#[cfg(feature = "Matrix3")]
98impl_two_arg_fxn!(Atan2M3x2F64, Matrix3x2<F64>, Matrix3x2<F64>, Matrix3x2<F64>, atan2_vec_op);
99#[cfg(feature = "Matrix4")]
100impl_two_arg_fxn!(Atan2M4F64, Matrix4<F64>, Matrix4<F64>, Matrix4<F64>, atan2_vec_op);
101#[cfg(feature = "Vector2")]
102impl_two_arg_fxn!(Atan2V2F64, Vector2<F64>, Vector2<F64>, Vector2<F64>, atan2_vec_op);
103#[cfg(feature = "Vector3")]
104impl_two_arg_fxn!(Atan2V3F64, Vector3<F64>, Vector3<F64>, Vector3<F64>, atan2_vec_op);
105#[cfg(feature = "Vector4")]
106impl_two_arg_fxn!(Atan2V4F64, Vector4<F64>, Vector4<F64>, Vector4<F64>, atan2_vec_op);
107#[cfg(feature = "RowVector2")]
108impl_two_arg_fxn!(Atan2R2F64, RowVector2<F64>, RowVector2<F64>, RowVector2<F64>, atan2_vec_op);
109#[cfg(feature = "RowVector3")]
110impl_two_arg_fxn!(Atan2R3F64, RowVector3<F64>, RowVector3<F64>, RowVector3<F64>, atan2_vec_op);
111#[cfg(feature = "RowVector4")]
112impl_two_arg_fxn!(Atan2R4F64, RowVector4<F64>, RowVector4<F64>, RowVector4<F64>, atan2_vec_op);
113#[cfg(feature = "RowVectorD")]
114impl_two_arg_fxn!(Atan2RDF64, RowDVector<F64>, RowDVector<F64>, RowDVector<F64>, atan2_vec_op);
115#[cfg(feature = "VectorD")]
116impl_two_arg_fxn!(Atan2VDF64, DVector<F64>, DVector<F64>, DVector<F64>, atan2_vec_op);
117#[cfg(feature = "MatrixD")]
118impl_two_arg_fxn!(Atan2MDF64, DMatrix<F64>, DMatrix<F64>, DMatrix<F64>, atan2_vec_op);
119
120
121fn impl_atan2_fxn(arg1_value: Value, arg2_value: Value) -> Result<Box<dyn MechFunction>, MechError> {
122  match (arg1_value,arg2_value) {
123    (Value::F32(arg1),Value::F32(arg2)) => Ok(Box::new(Atan2F32{arg1, arg2, out: new_ref(F32::zero())})),
124    (Value::MatrixF32(Matrix::Matrix1(arg1)),Value::MatrixF32(Matrix::Matrix1(arg2))) => Ok(Box::new(Atan2M1F32{arg1, arg2, out: new_ref(Matrix1::from_element(F32::zero()))})),
125    (Value::MatrixF32(Matrix::Matrix2(arg1)),Value::MatrixF32(Matrix::Matrix2(arg2))) => Ok(Box::new(Atan2M2F32{arg1, arg2, out: new_ref(Matrix2::from_element(F32::zero()))})),
126    (Value::MatrixF32(Matrix::Matrix3(arg1)),Value::MatrixF32(Matrix::Matrix3(arg2))) => Ok(Box::new(Atan2M3F32{arg1, arg2, out: new_ref(Matrix3::from_element(F32::zero()))})),
127    (Value::MatrixF32(Matrix::Matrix2x3(arg1)),Value::MatrixF32(Matrix::Matrix2x3(arg2))) => Ok(Box::new(Atan2M2x3F32{arg1, arg2, out: new_ref(Matrix2x3::from_element(F32::zero()))})),
128    (Value::MatrixF32(Matrix::Matrix3x2(arg1)),Value::MatrixF32(Matrix::Matrix3x2(arg2))) => Ok(Box::new(Atan2M3x2F32{arg1, arg2, out: new_ref(Matrix3x2::from_element(F32::zero()))})),
129    (Value::MatrixF32(Matrix::Matrix4(arg1)),Value::MatrixF32(Matrix::Matrix4(arg2))) => Ok(Box::new(Atan2M4F32{arg1, arg2, out: new_ref(Matrix4::from_element(F32::zero()))})),
130    (Value::MatrixF32(Matrix::Vector2(arg1)),Value::MatrixF32(Matrix::Vector2(arg2))) => Ok(Box::new(Atan2V2F32{arg1, arg2, out: new_ref(Vector2::from_element(F32::zero()))})),
131    (Value::MatrixF32(Matrix::Vector3(arg1)),Value::MatrixF32(Matrix::Vector3(arg2))) => Ok(Box::new(Atan2V3F32{arg1, arg2, out: new_ref(Vector3::from_element(F32::zero()))})),
132    (Value::MatrixF32(Matrix::Vector4(arg1)),Value::MatrixF32(Matrix::Vector4(arg2))) => Ok(Box::new(Atan2V4F32{arg1, arg2, out: new_ref(Vector4::from_element(F32::zero()))})),
133    (Value::MatrixF32(Matrix::RowVector2(arg1)),Value::MatrixF32(Matrix::RowVector2(arg2))) => Ok(Box::new(Atan2R2F32{arg1, arg2, out: new_ref(RowVector2::from_element(F32::zero()))})),
134    (Value::MatrixF32(Matrix::RowVector3(arg1)),Value::MatrixF32(Matrix::RowVector3(arg2))) => Ok(Box::new(Atan2R3F32{arg1, arg2, out: new_ref(RowVector3::from_element(F32::zero()))})),
135    (Value::MatrixF32(Matrix::RowVector4(arg1)),Value::MatrixF32(Matrix::RowVector4(arg2))) => Ok(Box::new(Atan2R4F32{arg1, arg2, out: new_ref(RowVector4::from_element(F32::zero()))})),
136    (Value::MatrixF32(Matrix::RowDVector(arg1)),Value::MatrixF32(Matrix::RowDVector(arg2))) => Ok(Box::new(Atan2RDF32{arg1: arg1.clone(), arg2, out: new_ref(RowDVector::from_element(arg1.borrow().ncols(),F32::zero()))})),
137    (Value::MatrixF32(Matrix::DVector(arg1)),Value::MatrixF32(Matrix::DVector(arg2))) => Ok(Box::new(Atan2VDF32{arg1: arg1.clone(), arg2, out: new_ref(DVector::from_element(arg1.borrow().nrows(),F32::zero()))})),
138    (Value::MatrixF32(Matrix::DMatrix(arg1)),Value::MatrixF32(Matrix::DMatrix(arg2))) => {
139      let rows = arg1.borrow().nrows();
140      let cols = arg1.borrow().ncols();
141      Ok(Box::new(Atan2MDF32{arg1, arg2, out: new_ref(DMatrix::from_element(rows,cols,F32::zero()))}))
142    },
143    (Value::F64(arg1),Value::F64(arg2)) => Ok(Box::new(Atan2F64{arg1, arg2, out: new_ref(F64::zero())})),
144    (Value::MatrixF64(Matrix::Matrix1(arg1)),Value::MatrixF64(Matrix::Matrix1(arg2))) => Ok(Box::new(Atan2M1F64{arg1, arg2, out: new_ref(Matrix1::from_element(F64::zero()))})),
145    (Value::MatrixF64(Matrix::Matrix2(arg1)),Value::MatrixF64(Matrix::Matrix2(arg2))) => Ok(Box::new(Atan2M2F64{arg1, arg2, out: new_ref(Matrix2::from_element(F64::zero()))})),
146    (Value::MatrixF64(Matrix::Matrix3(arg1)),Value::MatrixF64(Matrix::Matrix3(arg2))) => Ok(Box::new(Atan2M3F64{arg1, arg2, out: new_ref(Matrix3::from_element(F64::zero()))})),
147    (Value::MatrixF64(Matrix::Matrix2x3(arg1)),Value::MatrixF64(Matrix::Matrix2x3(arg2))) => Ok(Box::new(Atan2M2x3F64{arg1, arg2, out: new_ref(Matrix2x3::from_element(F64::zero()))})),
148    (Value::MatrixF64(Matrix::Matrix3x2(arg1)),Value::MatrixF64(Matrix::Matrix3x2(arg2))) => Ok(Box::new(Atan2M3x2F64{arg1, arg2, out: new_ref(Matrix3x2::from_element(F64::zero()))})),
149    (Value::MatrixF64(Matrix::Matrix4(arg1)),Value::MatrixF64(Matrix::Matrix4(arg2))) => Ok(Box::new(Atan2M4F64{arg1, arg2, out: new_ref(Matrix4::from_element(F64::zero()))})),
150    (Value::MatrixF64(Matrix::Vector2(arg1)),Value::MatrixF64(Matrix::Vector2(arg2))) => Ok(Box::new(Atan2V2F64{arg1, arg2, out: new_ref(Vector2::from_element(F64::zero()))})),
151    (Value::MatrixF64(Matrix::Vector3(arg1)),Value::MatrixF64(Matrix::Vector3(arg2))) => Ok(Box::new(Atan2V3F64{arg1, arg2, out: new_ref(Vector3::from_element(F64::zero()))})),
152    (Value::MatrixF64(Matrix::Vector4(arg1)),Value::MatrixF64(Matrix::Vector4(arg2))) => Ok(Box::new(Atan2V4F64{arg1, arg2, out: new_ref(Vector4::from_element(F64::zero()))})),
153    (Value::MatrixF64(Matrix::RowVector2(arg1)),Value::MatrixF64(Matrix::RowVector2(arg2))) => Ok(Box::new(Atan2R2F64{arg1, arg2, out: new_ref(RowVector2::from_element(F64::zero()))})),
154    (Value::MatrixF64(Matrix::RowVector3(arg1)),Value::MatrixF64(Matrix::RowVector3(arg2))) => Ok(Box::new(Atan2R3F64{arg1, arg2, out: new_ref(RowVector3::from_element(F64::zero()))})),
155    (Value::MatrixF64(Matrix::RowVector4(arg1)),Value::MatrixF64(Matrix::RowVector4(arg2))) => Ok(Box::new(Atan2R4F64{arg1, arg2, out: new_ref(RowVector4::from_element(F64::zero()))})),
156    (Value::MatrixF64(Matrix::RowDVector(arg1)),Value::MatrixF64(Matrix::RowDVector(arg2))) => Ok(Box::new(Atan2RDF64{arg1: arg1.clone(), arg2, out: new_ref(RowDVector::from_element(arg1.borrow().ncols(),F64::zero()))})),
157    (Value::MatrixF64(Matrix::DVector(arg1)),Value::MatrixF64(Matrix::DVector(arg2))) => Ok(Box::new(Atan2VDF64{arg1: arg1.clone(), arg2, out: new_ref(DVector::from_element(arg1.borrow().nrows(),F64::zero()))})),
158    (Value::MatrixF64(Matrix::DMatrix(arg1)),Value::MatrixF64(Matrix::DMatrix(arg2))) => {
159      let rows = arg1.borrow().nrows();
160      let cols = arg1.borrow().ncols();
161      Ok(Box::new(Atan2MDF64{arg1, arg2, out: new_ref(DMatrix::from_element(rows,cols,F64::zero()))}))
162    },
163    x => Err(MechError{file: file!().to_string(),  tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
164  }
165}
166
167pub struct MathAtan2 {}
168
169impl NativeFunctionCompiler for MathAtan2 {
170  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
171    if arguments.len() != 2 {
172      return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
173    }
174    let arg1 = arguments[0].clone();
175    let arg2 = arguments[1].clone();
176    match impl_atan2_fxn(arg1.clone(), arg2.clone()) {
177      Ok(fxn) => Ok(fxn),
178      Err(_) => {
179        match (arg1,arg2) {
180          (Value::MutableReference(arg1),Value::MutableReference(arg2)) => {impl_atan2_fxn(arg1.borrow().clone(),arg2.borrow().clone())}
181          (Value::MutableReference(arg1),arg2) => {impl_atan2_fxn(arg1.borrow().clone(),arg2.clone())}
182          (arg1,Value::MutableReference(arg2)) => {impl_atan2_fxn(arg1.clone(),arg2.borrow().clone())}
183          x => Err(MechError{file: file!().to_string(),  tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
184        }
185      }
186    }
187  }
188}