From 6afec96567c1735b539214d87fb9069ad0828904 Mon Sep 17 00:00:00 2001 From: hachem Date: Sun, 15 Sep 2024 14:06:15 +0200 Subject: Numeric Types and Complex Numbers --- .gitignore | 21 ++--- Cargo.toml | 5 ++ libmu/Cargo.toml | 6 ++ libmu/src/lib.rs | 4 + libmu/src/maths/complex.rs | 181 +++++++++++++++++++++++++++++++++++++++ libmu/src/maths/mod.rs | 2 + libmu/src/maths/numeric_types.rs | 47 ++++++++++ mu/Cargo.toml | 7 ++ mu/src/main.rs | 1 + 9 files changed, 258 insertions(+), 16 deletions(-) create mode 100644 Cargo.toml create mode 100644 libmu/Cargo.toml create mode 100644 libmu/src/lib.rs create mode 100644 libmu/src/maths/complex.rs create mode 100644 libmu/src/maths/mod.rs create mode 100644 libmu/src/maths/numeric_types.rs create mode 100644 mu/Cargo.toml create mode 100644 mu/src/main.rs diff --git a/.gitignore b/.gitignore index d01bd1a..476e319 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,10 @@ -# Generated by Cargo -# will have compiled files and executables +.vscode/ +.idea/ +.vs/ + debug/ target/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html Cargo.lock - -# These are backup files generated by rustfmt **/*.rs.bk - -# MSVC Windows builds of rustc generate these, which store debugging information -*.pdb - -# RustRover -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ \ No newline at end of file +*.pdb \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..26ca50d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = [ + "libmu", + "mu" +] \ No newline at end of file diff --git a/libmu/Cargo.toml b/libmu/Cargo.toml new file mode 100644 index 0000000..f451347 --- /dev/null +++ b/libmu/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "libmu" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/libmu/src/lib.rs b/libmu/src/lib.rs new file mode 100644 index 0000000..f96993c --- /dev/null +++ b/libmu/src/lib.rs @@ -0,0 +1,4 @@ +mod maths; + +pub use maths::complex; +pub use maths::numeric_types; diff --git a/libmu/src/maths/complex.rs b/libmu/src/maths/complex.rs new file mode 100644 index 0000000..dcd5902 --- /dev/null +++ b/libmu/src/maths/complex.rs @@ -0,0 +1,181 @@ +use crate::numeric_types::FloatTypes; +use std::ops; + +pub struct Complex { + pub real: T, + pub imaginary: T, +} + +impl Complex { + pub fn new(real: T, imaginary: T) -> Complex { + Complex { real, imaginary } + } + + pub fn get_conjugate(&self) -> Complex { + Complex::new(self.real, -self.imaginary) + } + + pub fn conjugate(&mut self) { + self.imaginary = -self.imaginary; + } + + pub fn phase(&self) -> T { + T::atan2(self.imaginary, self.real) + } + + pub fn norm(&self) -> T { + self.real * self.real + self.imaginary * self.imaginary + } + + pub fn abs(&self) -> T { + T::sqrt(self.norm()) + } +} + +impl ops::Add for Complex { + type Output = Complex; + + fn add(self, other: Complex) -> Complex { + Complex { + real: self.real + other.real, + imaginary: self.imaginary + other.imaginary, + } + } +} + +impl ops::Sub for Complex { + type Output = Complex; + + fn sub(self, other: Complex) -> Complex { + Complex { + real: self.real - other.real, + imaginary: self.imaginary - other.imaginary, + } + } +} + +impl ops::Mul for Complex { + type Output = Complex; + + fn mul(self, other: Complex) -> Complex { + Complex { + real: self.real * other.real - self.imaginary * other.imaginary, + imaginary: self.real * other.imaginary + self.imaginary * other.real, + } + } +} + +impl ops::Div for Complex { + type Output = Complex; + + fn div(self, other: Complex) -> Complex { + let denom = other.real * other.real + other.imaginary * other.imaginary; + Complex { + real: (self.real * other.real + self.imaginary * other.imaginary) / denom, + imaginary: (self.imaginary * other.real - self.real * other.imaginary) / denom, + } + } +} + +impl ops::Add for Complex { + type Output = Complex; + + fn add(self, other: T) -> Complex { + Complex { + real: self.real + other, + imaginary: self.imaginary, + } + } +} + +impl ops::Sub for Complex { + type Output = Complex; + + fn sub(self, other: T) -> Complex { + Complex { + real: self.real - other, + imaginary: self.imaginary, + } + } +} + +impl ops::Mul for Complex { + type Output = Complex; + + fn mul(self, other: T) -> Complex { + Complex { + real: self.real * other, + imaginary: self.imaginary * other, + } + } +} + +impl ops::Div for Complex { + type Output = Complex; + + fn div(self, other: T) -> Complex { + Complex { + real: self.real / other, + imaginary: self.imaginary / other, + } + } +} + +impl ops::AddAssign for Complex { + fn add_assign(&mut self, other: Complex) { + self.real += other.real; + self.imaginary += other.imaginary; + } +} + +impl ops::SubAssign for Complex { + fn sub_assign(&mut self, other: Complex) { + self.real -= other.real; + self.imaginary -= other.imaginary; + } +} + +impl ops::MulAssign for Complex { + fn mul_assign(&mut self, other: Complex) { + let new_real = self.real * other.real - self.imaginary * other.imaginary; + let new_imaginary = self.real * other.imaginary + self.imaginary * other.real; + self.real = new_real; + self.imaginary = new_imaginary; + } +} + +impl ops::DivAssign for Complex { + fn div_assign(&mut self, other: Complex) { + let denom = other.real * other.real + other.imaginary * other.imaginary; + let new_real = (self.real * other.real + self.imaginary * other.imaginary) / denom; + let new_imaginary = (self.imaginary * other.real - self.real * other.imaginary) / denom; + self.real = new_real; + self.imaginary = new_imaginary; + } +} + +impl ops::AddAssign for Complex { + fn add_assign(&mut self, other: T) { + self.real += other; + } +} + +impl ops::SubAssign for Complex { + fn sub_assign(&mut self, other: T) { + self.real -= other; + } +} + +impl ops::MulAssign for Complex { + fn mul_assign(&mut self, other: T) { + self.real *= other; + self.imaginary *= other; + } +} + +impl ops::DivAssign for Complex { + fn div_assign(&mut self, other: T) { + self.real /= other; + self.imaginary /= other; + } +} diff --git a/libmu/src/maths/mod.rs b/libmu/src/maths/mod.rs new file mode 100644 index 0000000..5986ab8 --- /dev/null +++ b/libmu/src/maths/mod.rs @@ -0,0 +1,2 @@ +pub mod complex; +pub mod numeric_types; diff --git a/libmu/src/maths/numeric_types.rs b/libmu/src/maths/numeric_types.rs new file mode 100644 index 0000000..dac766f --- /dev/null +++ b/libmu/src/maths/numeric_types.rs @@ -0,0 +1,47 @@ +use std::ops; + +pub trait NumericTypes: + Copy + + PartialOrd + + ops::Add + + ops::Mul + + ops::Sub + + ops::Div + + ops::Neg + + ops::AddAssign + + ops::SubAssign + + ops::MulAssign + + ops::DivAssign +{ +} + +pub trait IntTypes: NumericTypes {} +pub trait FloatTypes: NumericTypes { + fn sqrt(self) -> Self; + fn atan2(y: Self, x: Self) -> Self; +} + +impl FloatTypes for f32 { + fn sqrt(self) -> Self { + self.sqrt() + } + + fn atan2(y: Self, x: Self) -> Self { + y.atan2(x) + } +} + +impl FloatTypes for f64 { + fn sqrt(self) -> Self { + self.sqrt() + } + + fn atan2(y: Self, x: Self) -> Self { + y.atan2(x) + } +} + +impl NumericTypes for i32 {} +impl NumericTypes for i64 {} +impl NumericTypes for f32 {} +impl NumericTypes for f64 {} diff --git a/mu/Cargo.toml b/mu/Cargo.toml new file mode 100644 index 0000000..457443d --- /dev/null +++ b/mu/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "mu" +version = "0.1.0" +edition = "2021" + +[dependencies] +libmu = { path = "../libmu" } \ No newline at end of file diff --git a/mu/src/main.rs b/mu/src/main.rs new file mode 100644 index 0000000..f328e4d --- /dev/null +++ b/mu/src/main.rs @@ -0,0 +1 @@ +fn main() {} -- cgit v1.3