mech_math/bessel/
yn.rs

1use crate::*;
2use mech_core::*;
3use libm::{yn,ynf};
4use num_traits::*;
5#[cfg(feature = "matrix")]
6use mech_core::matrix::Matrix;
7
8// Yn ------------------------------------------------------------------------
9
10macro_rules! yn_op {
11  ($arg1:expr, $arg2:expr, $out:expr) => {
12    unsafe{(*$out) = yn((*$arg1) as i32,(*$arg2));}
13  };}
14
15macro_rules! yn_vec_op {
16  ($arg1:expr, $arg2:expr, $out:expr) => {
17    unsafe {
18      let arg1_deref = &(*$arg1);
19      let arg2_deref = &(*$arg2);
20      let mut out_deref = (&mut *$out);
21      for i in 0..arg1_deref.len() {
22        (out_deref[i]) = yn(arg1_deref[i] as i32,arg2_deref[i]);
23      }}};}
24
25macro_rules! ynf_op {
26  ($arg1:expr, $arg2:expr, $out:expr) => {
27    unsafe{(*$out) = ynf((*$arg1) as i32,(*$arg2));}
28  };}
29
30macro_rules! ynf_vec_op {
31  ($arg1:expr, $arg2:expr, $out:expr) => {
32    unsafe {
33      let arg1_deref = &(*$arg1);
34      let arg2_deref = &(*$arg2);
35      let mut out_deref = (&mut *$out);
36      for i in 0..arg1_deref.len() {
37        (out_deref[i]) = ynf(arg1_deref[i] as i32,arg2_deref[i]);
38      }}};}
39
40macro_rules! impl_two_arg_fxn {
41  ($struct_name:ident, $kind1:ty, $kind2:ty, $out_kind:ty, $op:ident) => {
42    #[derive(Debug)]
43    struct $struct_name {
44      arg1: Ref<$kind1>,
45      arg2: Ref<$kind2>,
46      out: Ref<$out_kind>,
47    }
48    impl MechFunctionImpl for $struct_name {
49      fn solve(&self) {
50        let arg1_ptr = self.arg1.as_ptr();
51        let arg2_ptr = self.arg2.as_ptr();
52        let out_ptr = self.out.as_mut_ptr();
53        $op!(arg1_ptr,arg2_ptr,out_ptr);
54      }
55      fn out(&self) -> Value { self.out.to_value() }
56      fn to_string(&self) -> String { format!("{:#?}", self) }
57    }
58    #[cfg(feature = "compiler")]
59    impl MechFunctionCompiler for $struct_name {
60      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
61        todo!();
62      }
63    }};}
64
65#[cfg(all(feature = "f32", feature = "matrix1"))]
66impl_two_arg_fxn!(YnM1F32, Matrix1<f32>, Matrix1<f32>, Matrix1<f32>, ynf_vec_op);
67#[cfg(all(feature = "f32", feature = "matrix2"))]
68impl_two_arg_fxn!(YnM2F32, Matrix2<f32>, Matrix2<f32>, Matrix2<f32>, ynf_vec_op);
69#[cfg(all(feature = "f32", feature = "matrix3"))]
70impl_two_arg_fxn!(YnM3F32, Matrix3<f32>, Matrix3<f32>, Matrix3<f32>, ynf_vec_op);
71#[cfg(all(feature = "f32", feature = "matrix2x3"))]
72impl_two_arg_fxn!(YnM2x3F32, Matrix2x3<f32>, Matrix2x3<f32>, Matrix2x3<f32>, ynf_vec_op);
73#[cfg(all(feature = "f32", feature = "matrix3"))]
74impl_two_arg_fxn!(YnM3x2F32, Matrix3x2<f32>, Matrix3x2<f32>, Matrix3x2<f32>, ynf_vec_op);
75#[cfg(all(feature = "f32", feature = "matrix4"))]
76impl_two_arg_fxn!(YnM4F32, Matrix4<f32>, Matrix4<f32>, Matrix4<f32>, ynf_vec_op);
77#[cfg(all(feature = "f32", feature = "vector2"))]
78impl_two_arg_fxn!(YnV2F32, Vector2<f32>, Vector2<f32>, Vector2<f32>, ynf_vec_op);
79#[cfg(all(feature = "f32", feature = "vector3"))]
80impl_two_arg_fxn!(YnV3F32, Vector3<f32>, Vector3<f32>, Vector3<f32>, ynf_vec_op);
81#[cfg(all(feature = "f32", feature = "vector4"))]
82impl_two_arg_fxn!(YnV4F32, Vector4<f32>, Vector4<f32>, Vector4<f32>, ynf_vec_op);
83#[cfg(all(feature = "f32", feature = "row_vector2"))]
84impl_two_arg_fxn!(YnR2F32, RowVector2<f32>, RowVector2<f32>, RowVector2<f32>, ynf_vec_op);
85#[cfg(all(feature = "f32", feature = "row_vector3"))]
86impl_two_arg_fxn!(YnR3F32, RowVector3<f32>, RowVector3<f32>, RowVector3<f32>, ynf_vec_op);
87#[cfg(all(feature = "f32", feature = "row_vector4"))]
88impl_two_arg_fxn!(YnR4F32, RowVector4<f32>, RowVector4<f32>, RowVector4<f32>, ynf_vec_op);
89#[cfg(all(feature = "f32", feature = "row_vectord"))]
90impl_two_arg_fxn!(YnRDF32, RowDVector<f32>, RowDVector<f32>, RowDVector<f32>, ynf_vec_op);
91#[cfg(all(feature = "f32", feature = "vectord"))]
92impl_two_arg_fxn!(YnVDF32, DVector<f32>, DVector<f32>, DVector<f32>, ynf_vec_op);
93#[cfg(all(feature = "f32", feature = "matrixd"))]
94impl_two_arg_fxn!(YnMDF32, DMatrix<f32>, DMatrix<f32>, DMatrix<f32>, ynf_vec_op);
95
96#[cfg(feature = "f32")]
97impl_two_arg_fxn!(YnF32, f32, f32, f32, ynf_op);
98
99#[cfg(all(feature = "f64", feature = "matrix1"))]
100impl_two_arg_fxn!(YnM1F64, Matrix1<f64>, Matrix1<f64>, Matrix1<f64>, yn_vec_op);
101#[cfg(all(feature = "f64", feature = "matrix2"))]
102impl_two_arg_fxn!(YnM2F64, Matrix2<f64>, Matrix2<f64>, Matrix2<f64>, yn_vec_op);
103#[cfg(all(feature = "f64", feature = "matrix3"))]
104impl_two_arg_fxn!(YnM3F64, Matrix3<f64>, Matrix3<f64>, Matrix3<f64>, yn_vec_op);
105#[cfg(all(feature = "f64", feature = "matrix2x3"))]
106impl_two_arg_fxn!(YnM2x3F64, Matrix2x3<f64>, Matrix2x3<f64>, Matrix2x3<f64>, yn_vec_op);
107#[cfg(all(feature = "f64", feature = "matrix3"))]
108impl_two_arg_fxn!(YnM3x2F64, Matrix3x2<f64>, Matrix3x2<f64>, Matrix3x2<f64>, yn_vec_op);
109#[cfg(all(feature = "f64", feature = "matrix4"))]
110impl_two_arg_fxn!(YnM4F64, Matrix4<f64>, Matrix4<f64>, Matrix4<f64>, yn_vec_op);
111#[cfg(all(feature = "f64", feature = "vector2"))]
112impl_two_arg_fxn!(YnV2F64, Vector2<f64>, Vector2<f64>, Vector2<f64>, yn_vec_op);
113#[cfg(all(feature = "f64", feature = "vector3"))]
114impl_two_arg_fxn!(YnV3F64, Vector3<f64>, Vector3<f64>, Vector3<f64>, yn_vec_op);
115#[cfg(all(feature = "f64", feature = "vector4"))]
116impl_two_arg_fxn!(YnV4F64, Vector4<f64>, Vector4<f64>, Vector4<f64>, yn_vec_op);
117#[cfg(all(feature = "f64", feature = "row_vector2"))]
118impl_two_arg_fxn!(YnR2F64, RowVector2<f64>, RowVector2<f64>, RowVector2<f64>, yn_vec_op);
119#[cfg(all(feature = "f64", feature = "row_vector3"))]
120impl_two_arg_fxn!(YnR3F64, RowVector3<f64>, RowVector3<f64>, RowVector3<f64>, yn_vec_op);
121#[cfg(all(feature = "f64", feature = "row_vector4"))]
122impl_two_arg_fxn!(YnR4F64, RowVector4<f64>, RowVector4<f64>, RowVector4<f64>, yn_vec_op);
123#[cfg(all(feature = "f64", feature = "row_vectord"))]
124impl_two_arg_fxn!(YnRDF64, RowDVector<f64>, RowDVector<f64>, RowDVector<f64>, yn_vec_op);
125#[cfg(all(feature = "f64", feature = "vectord"))]
126impl_two_arg_fxn!(YnVDF64, DVector<f64>, DVector<f64>, DVector<f64>, yn_vec_op);
127#[cfg(all(feature = "f64", feature = "matrixd"))]
128impl_two_arg_fxn!(YnMDF64, DMatrix<f64>, DMatrix<f64>, DMatrix<f64>, yn_vec_op);
129
130#[cfg(feature = "f64")]
131impl_two_arg_fxn!(YnF64, f64, f64, f64, yn_op);
132
133fn impl_yn_fxn(arg1_value: Value, arg2_value: Value) -> MResult<Box<dyn MechFunction>> {
134  match (arg1_value,arg2_value) {
135    #[cfg(feature = "f32")]
136    (Value::F32(arg1),Value::F32(arg2)) => Ok(Box::new(YnF32{arg1, arg2, out: Ref::new(f32::zero())})),
137    #[cfg(all(feature = "matrix1", feature = "f32"))]
138    (Value::MatrixF32(Matrix::Matrix1(arg1)),Value::MatrixF32(Matrix::Matrix1(arg2))) => Ok(Box::new(YnM1F32{arg1, arg2, out: Ref::new(Matrix1::from_element(f32::zero()))})),
139    #[cfg(all(feature = "matrix2", feature = "f32"))]
140    (Value::MatrixF32(Matrix::Matrix2(arg1)),Value::MatrixF32(Matrix::Matrix2(arg2))) => Ok(Box::new(YnM2F32{arg1, arg2, out: Ref::new(Matrix2::from_element(f32::zero()))})),
141    #[cfg(all(feature = "matrix3", feature = "f32"))]
142    (Value::MatrixF32(Matrix::Matrix3(arg1)),Value::MatrixF32(Matrix::Matrix3(arg2))) => Ok(Box::new(YnM3F32{arg1, arg2, out: Ref::new(Matrix3::from_element(f32::zero()))})),
143    #[cfg(all(feature = "matrix2x3", feature = "f32"))]
144    (Value::MatrixF32(Matrix::Matrix2x3(arg1)),Value::MatrixF32(Matrix::Matrix2x3(arg2))) => Ok(Box::new(YnM2x3F32{arg1, arg2, out: Ref::new(Matrix2x3::from_element(f32::zero()))})),
145    #[cfg(all(feature = "matrix3", feature = "f32"))]
146    (Value::MatrixF32(Matrix::Matrix3x2(arg1)),Value::MatrixF32(Matrix::Matrix3x2(arg2))) => Ok(Box::new(YnM3x2F32{arg1, arg2, out: Ref::new(Matrix3x2::from_element(f32::zero()))})),
147    #[cfg(all(feature = "matrix4", feature = "f32"))]
148    (Value::MatrixF32(Matrix::Matrix4(arg1)),Value::MatrixF32(Matrix::Matrix4(arg2))) => Ok(Box::new(YnM4F32{arg1, arg2, out: Ref::new(Matrix4::from_element(f32::zero()))})),
149    #[cfg(all(feature = "vector2", feature = "f32"))]
150    (Value::MatrixF32(Matrix::Vector2(arg1)),Value::MatrixF32(Matrix::Vector2(arg2))) => Ok(Box::new(YnV2F32{arg1, arg2, out: Ref::new(Vector2::from_element(f32::zero()))})),
151    #[cfg(all(feature = "vector3", feature = "f32"))]
152    (Value::MatrixF32(Matrix::Vector3(arg1)),Value::MatrixF32(Matrix::Vector3(arg2))) => Ok(Box::new(YnV3F32{arg1, arg2, out: Ref::new(Vector3::from_element(f32::zero()))})),
153    #[cfg(all(feature = "vector4", feature = "f32"))]
154    (Value::MatrixF32(Matrix::Vector4(arg1)),Value::MatrixF32(Matrix::Vector4(arg2))) => Ok(Box::new(YnV4F32{arg1, arg2, out: Ref::new(Vector4::from_element(f32::zero()))})),
155    #[cfg(all(feature = "row_vector2", feature = "f32"))]
156    (Value::MatrixF32(Matrix::RowVector2(arg1)),Value::MatrixF32(Matrix::RowVector2(arg2))) => Ok(Box::new(YnR2F32{arg1, arg2, out: Ref::new(RowVector2::from_element(f32::zero()))})),
157    #[cfg(all(feature = "row_vector3", feature = "f32"))]
158    (Value::MatrixF32(Matrix::RowVector3(arg1)),Value::MatrixF32(Matrix::RowVector3(arg2))) => Ok(Box::new(YnR3F32{arg1, arg2, out: Ref::new(RowVector3::from_element(f32::zero()))})),
159    #[cfg(all(feature = "row_vector4", feature = "f32"))]
160    (Value::MatrixF32(Matrix::RowVector4(arg1)),Value::MatrixF32(Matrix::RowVector4(arg2))) => Ok(Box::new(YnR4F32{arg1, arg2, out: Ref::new(RowVector4::from_element(f32::zero()))})),
161    #[cfg(all(feature = "row_vectord", feature = "f32"))]
162    (Value::MatrixF32(Matrix::RowDVector(arg1)),Value::MatrixF32(Matrix::RowDVector(arg2))) => Ok(Box::new(YnRDF32{arg1: arg1.clone(), arg2, out: Ref::new(RowDVector::from_element(arg1.borrow().ncols(),f32::zero()))})),
163    #[cfg(all(feature = "vectord", feature = "f32"))]
164    (Value::MatrixF32(Matrix::DVector(arg1)),Value::MatrixF32(Matrix::DVector(arg2))) => Ok(Box::new(YnVDF32{arg1: arg1.clone(), arg2, out: Ref::new(DVector::from_element(arg1.borrow().nrows(),f32::zero()))})),
165    #[cfg(all(feature = "matrixd", feature = "f32"))]
166    (Value::MatrixF32(Matrix::DMatrix(arg1)),Value::MatrixF32(Matrix::DMatrix(arg2))) => {
167      let rows = arg1.borrow().nrows();
168      let cols = arg1.borrow().ncols();
169      Ok(Box::new(YnMDF32{arg1, arg2, out: Ref::new(DMatrix::from_element(rows,cols,f32::zero()))}))
170    },
171    #[cfg(feature = "f64")]
172    (Value::F64(arg1),Value::F64(arg2)) => Ok(Box::new(YnF64{arg1, arg2, out: Ref::new(f64::zero())})),
173    #[cfg(all(feature = "matrix1", feature = "f64"))]
174    (Value::MatrixF64(Matrix::Matrix1(arg1)),Value::MatrixF64(Matrix::Matrix1(arg2))) => Ok(Box::new(YnM1F64{arg1, arg2, out: Ref::new(Matrix1::from_element(f64::zero()))})),
175    #[cfg(all(feature = "matrix2", feature = "f64"))]
176    (Value::MatrixF64(Matrix::Matrix2(arg1)),Value::MatrixF64(Matrix::Matrix2(arg2))) => Ok(Box::new(YnM2F64{arg1, arg2, out: Ref::new(Matrix2::from_element(f64::zero()))})),
177    #[cfg(all(feature = "matrix3", feature = "f64"))]
178    (Value::MatrixF64(Matrix::Matrix3(arg1)),Value::MatrixF64(Matrix::Matrix3(arg2))) => Ok(Box::new(YnM3F64{arg1, arg2, out: Ref::new(Matrix3::from_element(f64::zero()))})),
179    #[cfg(all(feature = "matrix2x3", feature = "f64"))]
180    (Value::MatrixF64(Matrix::Matrix2x3(arg1)),Value::MatrixF64(Matrix::Matrix2x3(arg2))) => Ok(Box::new(YnM2x3F64{arg1, arg2, out: Ref::new(Matrix2x3::from_element(f64::zero()))})),
181    #[cfg(all(feature = "matrix3", feature = "f64"))]
182    (Value::MatrixF64(Matrix::Matrix3x2(arg1)),Value::MatrixF64(Matrix::Matrix3x2(arg2))) => Ok(Box::new(YnM3x2F64{arg1, arg2, out: Ref::new(Matrix3x2::from_element(f64::zero()))})),
183    #[cfg(all(feature = "matrix4", feature = "f64"))]
184    (Value::MatrixF64(Matrix::Matrix4(arg1)),Value::MatrixF64(Matrix::Matrix4(arg2))) => Ok(Box::new(YnM4F64{arg1, arg2, out: Ref::new(Matrix4::from_element(f64::zero()))})),
185    #[cfg(all(feature = "vector2", feature = "f64"))]
186    (Value::MatrixF64(Matrix::Vector2(arg1)),Value::MatrixF64(Matrix::Vector2(arg2))) => Ok(Box::new(YnV2F64{arg1, arg2, out: Ref::new(Vector2::from_element(f64::zero()))})),
187    #[cfg(all(feature = "vector3", feature = "f64"))]
188    (Value::MatrixF64(Matrix::Vector3(arg1)),Value::MatrixF64(Matrix::Vector3(arg2))) => Ok(Box::new(YnV3F64{arg1, arg2, out: Ref::new(Vector3::from_element(f64::zero()))})),
189    #[cfg(all(feature = "vector4", feature = "f64"))]
190    (Value::MatrixF64(Matrix::Vector4(arg1)),Value::MatrixF64(Matrix::Vector4(arg2))) => Ok(Box::new(YnV4F64{arg1, arg2, out: Ref::new(Vector4::from_element(f64::zero()))})),
191    #[cfg(all(feature = "row_vector2", feature = "f64"))]
192    (Value::MatrixF64(Matrix::RowVector2(arg1)),Value::MatrixF64(Matrix::RowVector2(arg2))) => Ok(Box::new(YnR2F64{arg1, arg2, out: Ref::new(RowVector2::from_element(f64::zero()))})),
193    #[cfg(all(feature = "row_vector3", feature = "f64"))]
194    (Value::MatrixF64(Matrix::RowVector3(arg1)),Value::MatrixF64(Matrix::RowVector3(arg2))) => Ok(Box::new(YnR3F64{arg1, arg2, out: Ref::new(RowVector3::from_element(f64::zero()))})),
195    #[cfg(all(feature = "row_vector4", feature = "f64"))]
196    (Value::MatrixF64(Matrix::RowVector4(arg1)),Value::MatrixF64(Matrix::RowVector4(arg2))) => Ok(Box::new(YnR4F64{arg1, arg2, out: Ref::new(RowVector4::from_element(f64::zero()))})),
197    #[cfg(all(feature = "row_vectord", feature = "f64"))]
198    (Value::MatrixF64(Matrix::RowDVector(arg1)),Value::MatrixF64(Matrix::RowDVector(arg2))) => Ok(Box::new(YnRDF64{arg1: arg1.clone(), arg2, out: Ref::new(RowDVector::from_element(arg1.borrow().ncols(),f64::zero()))})),
199    #[cfg(all(feature = "vectord", feature = "f64"))]
200    (Value::MatrixF64(Matrix::DVector(arg1)),Value::MatrixF64(Matrix::DVector(arg2))) => Ok(Box::new(YnVDF64{arg1: arg1.clone(), arg2, out: Ref::new(DVector::from_element(arg1.borrow().nrows(),f64::zero()))})),
201    #[cfg(all(feature = "matrixd", feature = "f64"))]
202    (Value::MatrixF64(Matrix::DMatrix(arg1)),Value::MatrixF64(Matrix::DMatrix(arg2))) => {
203      let rows = arg1.borrow().nrows();
204      let cols = arg1.borrow().ncols();
205      Ok(Box::new(YnMDF64{arg1, arg2, out: Ref::new(DMatrix::from_element(rows,cols,f64::zero()))}))
206    },
207    (arg1,arg2) => Err(MechError2::new(
208        UnhandledFunctionArgumentKind2 { arg: (arg1.kind(),arg2.kind()), fxn_name: "math/bessel/yn".to_string() },
209        None
210      ).with_compiler_loc()
211    ),
212  }
213}
214
215pub struct MathYn {}
216
217impl NativeFunctionCompiler for MathYn {
218  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
219    if arguments.len() != 2 {
220      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
221    }
222    let arg1 = arguments[0].clone();
223    let arg2 = arguments[1].clone();
224    match impl_yn_fxn(arg1.clone(), arg2.clone()) {
225      Ok(fxn) => Ok(fxn),
226      Err(_) => {
227        match (arg1,arg2) {
228          (Value::MutableReference(arg1),Value::MutableReference(arg2)) => {impl_yn_fxn(arg1.borrow().clone(),arg2.borrow().clone())}
229          (Value::MutableReference(arg1),arg2) => {impl_yn_fxn(arg1.borrow().clone(),arg2.clone())}
230          (arg1,Value::MutableReference(arg2)) => {impl_yn_fxn(arg1.clone(),arg2.borrow().clone())}
231          (arg1,arg2) => Err(MechError2::new(
232              UnhandledFunctionArgumentKind2 { arg: (arg1.kind(),arg2.kind()), fxn_name: "math/bessel/yn".to_string() },
233              None
234            ).with_compiler_loc()
235          ),
236        }
237      }
238    }
239  }
240}
241
242register_descriptor! {
243  FunctionCompilerDescriptor {
244    name: "math/bessel/yn",
245    ptr: &MathYn{},
246  }
247}