aboutsummaryrefslogtreecommitdiff
path: root/src/maths/numeric.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/maths/numeric.rs')
-rw-r--r--src/maths/numeric.rs101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/maths/numeric.rs b/src/maths/numeric.rs
new file mode 100644
index 0000000..f5a649e
--- /dev/null
+++ b/src/maths/numeric.rs
@@ -0,0 +1,101 @@
+use crate::Complex;
+use core::ops;
+
+macro_rules! impl_numeric {
+ ($($t:ty),*) => {
+ $(
+ impl Numeric for $t {
+ fn zero() -> Self {
+ 0 as $t
+ }
+
+ fn one() -> Self {
+ 1 as $t
+ }
+ }
+ )*
+ };
+}
+
+macro_rules! impl_cnumeric {
+ ($($t:ty),*) => {
+ $(impl Numeric for Complex<$t> {
+ fn zero() -> Self { Complex::new(0.0, 0.0) }
+ fn one() -> Self { Complex::new(1.0, 0.0) }
+ })*
+ };
+}
+
+macro_rules! impl_float {
+ ($($t:ty, $sqrt_fn:path, $atan2_fn:path),*) => {
+ $(
+ impl Float for $t {
+ fn sqrt(self) -> Self {
+ $sqrt_fn(self)
+ }
+
+ fn atan2(y: Self, x: Self) -> Self {
+ $atan2_fn(y, x)
+ }
+ }
+ )*
+ };
+}
+
+macro_rules! impl_cfloat {
+ ($($t:ty, $sqrt_fn:path, $atan2_fn:path, $cos_fn:path, $sin_fn:path),*) => {
+ $(
+ impl Float for Complex<$t> {
+ fn sqrt(self) -> Self {
+ let r = self.abs();
+ let theta = self.phase();
+
+ let sqrt_r = $sqrt_fn(r);
+ let sqrt_theta = theta / 2.0;
+
+ Complex::new(
+ sqrt_r * $cos_fn(sqrt_theta),
+ sqrt_r * $sin_fn(sqrt_theta),
+ )
+ }
+
+ fn atan2(y: Self, x: Self) -> Self {
+ Complex::new(
+ $atan2_fn(y.real, x.real),
+ $atan2_fn(y.imaginary, x.imaginary),
+ )
+ }
+ }
+ )*
+ };
+}
+
+pub trait Numeric:
+ Copy
+ + PartialOrd
+ + ops::Add<Output = Self>
+ + ops::Mul<Output = Self>
+ + ops::Sub<Output = Self>
+ + ops::Div<Output = Self>
+ + ops::Neg<Output = Self>
+ + ops::AddAssign
+ + ops::SubAssign
+ + ops::MulAssign
+ + ops::DivAssign
+{
+ fn zero() -> Self;
+ fn one() -> Self;
+}
+
+impl_numeric!(i32, i64, f32, f64);
+impl_cnumeric!(f32, f64);
+impl_float!(f32, libm::sqrtf, libm::atan2f);
+impl_float!(f64, libm::sqrt, libm::atan2);
+impl_cfloat!(f32, libm::sqrtf, libm::atan2f, libm::cosf, libm::sinf);
+impl_cfloat!(f64, libm::sqrt, libm::atan2, libm::cos, libm::sin);
+
+pub trait Integer: Numeric {}
+pub trait Float: Numeric {
+ fn sqrt(self) -> Self;
+ fn atan2(y: Self, x: Self) -> Self;
+}