diff options
| author | hachem <im@hachem.wtf> | 2024-09-24 21:33:51 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2024-09-24 21:33:51 +0200 |
| commit | c07ab7911bd50d0060841690a863333a9a3f226d (patch) | |
| tree | 5deb12fc8234d553318e4615ae21ddfcc6db4ab4 /libpsi/src | |
| parent | 26010345eedc716c70e8a4219005db19b266c960 (diff) | |
rename project
Diffstat (limited to 'libpsi/src')
| -rw-r--r-- | libpsi/src/core/component.rs | 141 | ||||
| -rw-r--r-- | libpsi/src/core/gates.rs | 22 | ||||
| -rw-r--r-- | libpsi/src/core/mod.rs | 4 | ||||
| -rw-r--r-- | libpsi/src/lib.rs | 10 | ||||
| -rw-r--r-- | libpsi/src/maths/complex.rs | 82 | ||||
| -rw-r--r-- | libpsi/src/maths/complex_ops.rs | 147 | ||||
| -rw-r--r-- | libpsi/src/maths/matrix.rs | 190 | ||||
| -rw-r--r-- | libpsi/src/maths/matrix_ops.rs | 62 | ||||
| -rw-r--r-- | libpsi/src/maths/mod.rs | 16 | ||||
| -rw-r--r-- | libpsi/src/maths/numeric_float.rs | 65 | ||||
| -rw-r--r-- | libpsi/src/maths/numeric_int.rs | 44 | ||||
| -rw-r--r-- | libpsi/src/maths/numeric_traits.rs | 24 | ||||
| -rw-r--r-- | libpsi/src/maths/vector.rs | 268 | ||||
| -rw-r--r-- | libpsi/src/maths/vector_ops.rs | 107 |
14 files changed, 0 insertions, 1182 deletions
diff --git a/libpsi/src/core/component.rs b/libpsi/src/core/component.rs deleted file mode 100644 index 41b7cc7..0000000 --- a/libpsi/src/core/component.rs +++ /dev/null @@ -1,141 +0,0 @@ -use crate::{complex, ColumnVector, Complex, Matrix, Vector, VectorMatrix}; -use core::{fmt, ops}; - -pub type QuantumBit = ColumnVector<Complex<f64>>; -pub type QuantumGate = Matrix<Complex<f64>>; - -#[macro_export] -macro_rules! count { - () => { 0 }; - ($head:expr $(,$tail:expr)*) => { 1 + count!($( $tail ),*) }; -} - -#[macro_export] -macro_rules! qubit { - ($(($re:expr, $im:expr)),*) => { - { - let mut vector = Vec::new(); - $( - vector.push(complex!($re, $im)); - )* - QuantumBit::new(vector) - } - }; -} - -#[macro_export] -macro_rules! quantum_register { - ($($bit:expr),*) => { - { - const N: usize = count!($($bit),*); - let mut bits: [QuantumBit; N] = [$($bit),*]; - QuantumRegister::from(&mut bits) - } - }; -} - -pub struct ClassicalRegister { - bits: Vec<i32>, -} - -pub struct QuantumRegister { - state: ColumnVector<Complex<f64>>, - qubits: Vec<QuantumBit>, -} - -impl QuantumBit { - pub fn measure(&self) -> i32 { - let alpha_abs = self[0].abs(); - let beta_abs = self[1].abs(); - - let alpha_norm = alpha_abs * alpha_abs; - let beta_norm = beta_abs * beta_abs; - - if alpha_norm > beta_norm { - 0 - } else { - 1 - } - } - - pub fn state_0() -> QuantumBit { - QuantumBit::new(vec![complex!(1.0, 0.0), complex!(0.0, 0.0)]) - } - - pub fn state_1() -> QuantumBit { - QuantumBit::new(vec![complex!(0.0, 0.0), complex!(1.0, 0.0)]) - } -} - -impl ClassicalRegister { - pub fn new(count: usize) -> ClassicalRegister { - ClassicalRegister { - bits: Vec::with_capacity(count), - } - } - - pub fn set_bits(&mut self, bits: Vec<i32>) { - self.bits = bits; - } -} - -impl QuantumRegister { - fn update(&mut self) { - let matrices: Vec<Matrix<Complex<f64>>> = - self.qubits.iter().map(|qubit| qubit.to_matrix()).collect(); - let mut new_result = matrices[0].clone(); - for matrix in &matrices[1..] { - new_result = new_result.kronecker(matrix); - } - - self.state = ColumnVector::from_matrix(&new_result); - } - - pub fn from(bits: &mut [QuantumBit]) -> QuantumRegister { - let mut register = QuantumRegister { - qubits: bits.to_vec(), - state: ColumnVector::new(vec![]), - }; - - register.update(); - register - } - - pub fn measure(&self, classical_register: &mut ClassicalRegister) { - classical_register.set_bits(self.qubits.iter().map(|qubit| qubit.measure()).collect()); - } - - pub fn apply(&mut self, gate: &QuantumGate, index: usize) { - let result: ColumnVector<Complex<f64>> = self.state.mul_matrix(gate).unwrap(); - self.qubits[index] = result; - self.update(); - } -} - -impl ops::Index<usize> for QuantumRegister { - type Output = QuantumBit; - - fn index(&self, index: usize) -> &Self::Output { - &self.qubits[index] - } -} - -impl ops::IndexMut<usize> for QuantumRegister { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.qubits[index] - } -} - -impl ops::Index<usize> for ClassicalRegister { - type Output = i32; - - fn index(&self, index: usize) -> &Self::Output { - &self.bits[index] - } -} - -impl ops::IndexMut<usize> for ClassicalRegister { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.bits[index] - } -} diff --git a/libpsi/src/core/gates.rs b/libpsi/src/core/gates.rs deleted file mode 100644 index e9077ad..0000000 --- a/libpsi/src/core/gates.rs +++ /dev/null @@ -1,22 +0,0 @@ -use crate::{complex, matrix, QuantumGate}; - -#[rustfmt::skip] -lazy_static::lazy_static! { - pub static ref HADAMARD: QuantumGate = matrix!([complex!(1.0, 0.0), complex!( 1.0, 0.0)]; - [complex!(1.0, 0.0), complex!(-1.0, 0.0)]) * - complex!(1.0/2.0_f64.sqrt(), 0.0); - - pub static ref PAULI_X: QuantumGate = matrix!([complex!(0.0, 0.0), complex!(1.0, 0.0)]; - [complex!(1.0, 0.0), complex!(0.0, 0.0)]); - - pub static ref PAULI_Y: QuantumGate = matrix!([complex!(0.0, 0.0), complex!(0.0, -1.0)]; - [complex!(0.0, 1.0), complex!(0.0, 0.0)]); - - pub static ref PAULI_Z: QuantumGate = matrix!([complex!(1.0, 0.0), complex!( 0.0, 0.0)]; - [complex!(0.0, 0.0), complex!(-1.0, 0.0)]); - - pub static ref CNOT: QuantumGate = matrix!([complex!(1.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0)]; - [complex!(0.0, 0.0), complex!(1.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0)]; - [complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(1.0, 0.0)]; - [complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(1.0, 0.0), complex!(0.0, 0.0)]); -} diff --git a/libpsi/src/core/mod.rs b/libpsi/src/core/mod.rs deleted file mode 100644 index 374c555..0000000 --- a/libpsi/src/core/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod component; -pub mod gates; - -pub use gates::*; diff --git a/libpsi/src/lib.rs b/libpsi/src/lib.rs deleted file mode 100644 index af50663..0000000 --- a/libpsi/src/lib.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub mod core; -pub mod maths; - -pub use maths::complex::*; -pub use maths::matrix::*; -pub use maths::numeric_traits::*; -pub use maths::vector::*; - -pub use core::component::*; -pub use core::gates; diff --git a/libpsi/src/maths/complex.rs b/libpsi/src/maths/complex.rs deleted file mode 100644 index bb19510..0000000 --- a/libpsi/src/maths/complex.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::Float; -use core::fmt; - -use super::Numeric; - -#[macro_export] -macro_rules! complex { - ($real:expr, $imaginary:expr) => { - $crate::Complex::new($real, $imaginary) - }; -} - -#[derive(Copy, Clone, PartialOrd, PartialEq)] -pub struct Complex<T: Float> { - pub real: T, - pub imaginary: T, -} - -impl<T: Float + fmt::Debug> fmt::Debug for Complex<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "Complex {{ real: {:?}, imaginary: {:?} }}", - self.real, self.imaginary - ) - } -} - -impl<T: Float + fmt::Display> fmt::Display for Complex<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{} + {}i", self.real, self.imaginary) - } -} - -impl Numeric for Complex<f32> { - fn zero() -> Self { - Complex::new(0.0, 0.0) - } - - fn one() -> Self { - Complex::new(1.0, 0.0) - } -} - -impl Numeric for Complex<f64> { - fn zero() -> Self { - Complex::new(0.0, 0.0) - } - - fn one() -> Self { - Complex::new(1.0, 0.0) - } -} - -impl<T: Float> Complex<T> { - pub fn new(real: T, imaginary: T) -> Complex<T> { - Complex { real, imaginary } - } - - pub fn get_conjugate(&self) -> Complex<T> { - Complex { - real: self.real, - imaginary: -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()) - } -} diff --git a/libpsi/src/maths/complex_ops.rs b/libpsi/src/maths/complex_ops.rs deleted file mode 100644 index bfcf920..0000000 --- a/libpsi/src/maths/complex_ops.rs +++ /dev/null @@ -1,147 +0,0 @@ -use super::{Complex, Float}; -use core::ops; - -impl<T: Float> ops::Neg for Complex<T> { - type Output = Complex<T>; - - fn neg(self) -> Complex<T> { - Complex { - real: -self.real, - imaginary: -self.imaginary, - } - } -} - -impl<T: Float> From<T> for Complex<T> { - fn from(real: T) -> Complex<T> { - Complex { - real, - imaginary: T::zero(), - } - } -} - -// Complex-Complex -impl<T: Float> ops::Add for Complex<T> { - type Output = Complex<T>; - - fn add(self, other: Complex<T>) -> Complex<T> { - Complex { - real: self.real - other.real, - imaginary: self.imaginary - other.imaginary, - } - } -} - -impl<T: Float> ops::Sub for Complex<T> { - type Output = Complex<T>; - - fn sub(self, other: Complex<T>) -> Complex<T> { - Complex { - real: self.real - other.real, - imaginary: self.imaginary - other.imaginary, - } - } -} - -impl<T: Float> ops::Mul for Complex<T> { - type Output = Complex<T>; - - fn mul(self, other: Complex<T>) -> Complex<T> { - Complex { - real: self.real * other.real - self.imaginary * other.imaginary, - imaginary: self.real * other.imaginary + self.imaginary * other.real, - } - } -} - -impl<T: Float> ops::Div for Complex<T> { - type Output = Complex<T>; - - fn div(self, other: Complex<T>) -> Complex<T> { - 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, - } - } -} - -// Complex-Complex, Assign -impl<T: Float> ops::AddAssign for Complex<T> { - fn add_assign(&mut self, other: Complex<T>) { - self.real += other.real; - self.imaginary += other.imaginary; - } -} - -impl<T: Float> ops::SubAssign for Complex<T> { - fn sub_assign(&mut self, other: Complex<T>) { - self.real -= other.real; - self.imaginary -= other.imaginary; - } -} - -impl<T: Float> ops::MulAssign for Complex<T> { - fn mul_assign(&mut self, other: Complex<T>) { - 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<T: Float> ops::DivAssign for Complex<T> { - fn div_assign(&mut self, other: Complex<T>) { - 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; - } -} - -// Real-Complex -impl<T: Float> ops::Add<T> for Complex<T> { - type Output = Complex<T>; - - fn add(self, other: T) -> Complex<T> { - Complex { - real: self.real + other, - imaginary: self.imaginary, - } - } -} - -impl<T: Float> ops::Sub<T> for Complex<T> { - type Output = Complex<T>; - - fn sub(self, other: T) -> Complex<T> { - Complex { - real: self.real - other, - imaginary: self.imaginary, - } - } -} - -impl<T: Float> ops::Mul<T> for Complex<T> { - type Output = Complex<T>; - - fn mul(self, other: T) -> Complex<T> { - Complex { - real: self.real * other, - imaginary: self.imaginary * other, - } - } -} - -impl<T: Float> ops::Div<T> for Complex<T> { - type Output = Complex<T>; - - fn div(self, other: T) -> Complex<T> { - Complex { - real: self.real / other, - imaginary: self.imaginary / other, - } - } -} diff --git a/libpsi/src/maths/matrix.rs b/libpsi/src/maths/matrix.rs deleted file mode 100644 index 975c92d..0000000 --- a/libpsi/src/maths/matrix.rs +++ /dev/null @@ -1,190 +0,0 @@ -use super::Float; -use core::{fmt, ops}; - -#[macro_export] -macro_rules! matrix { - ( $( $( $x:expr ),* );* ) => {{ - let mut data = Vec::new(); - let mut rows = 0; - let mut cols = 0; - - $( - let row_data = $( $x )*; - if cols == 0 { - cols = row_data.len(); - } - assert_eq!(cols, row_data.len(), "All rows must have the same number of columns."); - data.extend(row_data); - rows += 1; - )* - - $crate::Matrix::new(rows, cols, data) - }}; -} - -#[derive(Clone)] -pub struct Matrix<T: Float> { - pub data: Vec<T>, - pub rows: usize, - pub cols: usize, -} - -impl<T: Float> Matrix<T> { - pub fn new(rows: usize, cols: usize, data: Vec<T>) -> Self { - Matrix { data, rows, cols } - } - - pub fn get(&self, row: usize, col: usize) -> T { - self.data[row * self.cols + col] - } - - pub fn set(&mut self, row: usize, col: usize, value: T) { - self.data[row * self.cols + col] = value; - } - - pub fn dot(&self, other: &Self) -> Option<Matrix<T>> { - if self.cols != other.rows { - return None; - } - - let mut result = Matrix::new( - self.rows, - other.cols, - vec![T::zero(); self.rows * other.cols], - ); - for i in 0..self.rows { - for j in 0..other.cols { - let mut sum = T::zero(); - for k in 0..self.cols { - sum = sum + (self.get(i, k) * other.get(k, j)); - } - result.set(i, j, sum); - } - } - Some(result) - } - - pub fn kronecker(&self, other: &Self) -> Matrix<T> { - let new_rows = self.rows * other.rows; - let new_cols = self.cols * other.cols; - - let mut result = Matrix::new(new_rows, new_cols, vec![T::zero(); new_rows * new_cols]); - - for i in 0..self.rows { - for j in 0..self.cols { - let self_val = self.get(i, j); - for k in 0..other.rows { - for l in 0..other.cols { - let result_row = i * other.rows + k; - let result_col = j * other.cols + l; - result.set(result_row, result_col, self_val.clone() * other.get(k, l)); - } - } - } - } - - result - } - - pub fn transpose(&self) -> Matrix<T> { - let mut result = Matrix::new(self.cols, self.rows, vec![T::zero(); self.cols * self.rows]); - - for i in 0..self.rows { - for j in 0..self.cols { - let value = self.get(i, j); - result.set(j, i, value); - } - } - - result - } - - pub fn add_to(&self, other: &Self) -> Option<Matrix<T>> { - if self.rows != other.rows || self.cols != other.cols { - return None; - } - - let mut result = Matrix::new(self.rows, self.cols, vec![T::zero(); self.rows * self.cols]); - - for i in 0..self.rows { - for j in 0..self.cols { - let sum = self.get(i, j) + other.get(i, j); - result.set(i, j, sum); - } - } - Some(result) - } - - pub fn subtract(&self, other: &Self) -> Option<Matrix<T>> { - if self.rows != other.rows || self.cols != other.cols { - return None; - } - - let mut result = Matrix::new(self.rows, self.cols, vec![T::zero(); self.rows * self.cols]); - - for i in 0..self.rows { - for j in 0..self.cols { - let diff = self.get(i, j) - other.get(i, j); - result.set(i, j, diff); - } - } - Some(result) - } - - pub fn scale(&self, scalar: T) -> Matrix<T> { - let mut result = Matrix::new(self.rows, self.cols, vec![T::zero(); self.rows * self.cols]); - - for i in 0..self.rows { - for j in 0..self.cols { - let scaled_value = self.get(i, j) * scalar; - result.set(i, j, scaled_value); - } - } - result - } -} - -impl<T: Float> ops::Index<(usize, usize)> for Matrix<T> { - type Output = T; - - fn index(&self, index: (usize, usize)) -> &Self::Output { - &self.data[index.0 * self.cols + index.1] - } -} - -impl<T: Float> ops::IndexMut<(usize, usize)> for Matrix<T> { - fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output { - &mut self.data[index.0 * self.cols + index.1] - } -} - -impl<T: Float + fmt::Debug> fmt::Debug for Matrix<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for i in 0..self.rows { - for j in 0..self.cols { - write!(f, "{:?} ", self.get(i, j))?; - } - writeln!(f)?; - } - Ok(()) - } -} - -impl<T: Float + fmt::Display> fmt::Display for Matrix<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for i in 0..self.rows { - write!(f, "[")?; - for j in 0..self.cols { - write!(f, "{}", self.get(i, j))?; - if j != self.cols - 1 { - write!(f, " ")?; - } - } - write!(f, "]")?; - if i != self.rows - 1 { - write!(f, "\n")?; - } - } - Ok(()) - } -} diff --git a/libpsi/src/maths/matrix_ops.rs b/libpsi/src/maths/matrix_ops.rs deleted file mode 100644 index 15ab28b..0000000 --- a/libpsi/src/maths/matrix_ops.rs +++ /dev/null @@ -1,62 +0,0 @@ -use super::{Float, Matrix}; -use core::ops; - -impl<T: Float> ops::Add<&Matrix<T>> for Matrix<T> { - type Output = Option<Matrix<T>>; - - fn add(self, other: &Matrix<T>) -> Self::Output { - self.add_to(other) - } -} - -impl<T: Float> ops::Sub<&Matrix<T>> for Matrix<T> { - type Output = Option<Matrix<T>>; - - fn sub(self, other: &Matrix<T>) -> Self::Output { - self.subtract(other) - } -} - -impl<T: Float> ops::Mul<T> for Matrix<T> { - type Output = Matrix<T>; - - fn mul(self, scalar: T) -> Self::Output { - self.scale(scalar) - } -} - -impl<T: Float> ops::Div<T> for Matrix<T> { - type Output = Matrix<T>; - - fn div(self, scalar: T) -> Self::Output { - self.scale(T::one() / scalar) - } -} - -impl<T: Float> ops::AddAssign<&Matrix<T>> for Matrix<T> { - fn add_assign(&mut self, other: &Matrix<T>) { - if let Some(result) = self.add_to(other) { - *self = result; - } - } -} - -impl<T: Float> ops::SubAssign<&Matrix<T>> for Matrix<T> { - fn sub_assign(&mut self, other: &Matrix<T>) { - if let Some(result) = self.subtract(other) { - *self = result; - } - } -} - -impl<T: Float> ops::MulAssign<T> for Matrix<T> { - fn mul_assign(&mut self, scalar: T) { - *self = self.scale(scalar); - } -} - -impl<T: Float> ops::DivAssign<T> for Matrix<T> { - fn div_assign(&mut self, scalar: T) { - *self = self.scale(T::one() / scalar); - } -} diff --git a/libpsi/src/maths/mod.rs b/libpsi/src/maths/mod.rs deleted file mode 100644 index a2b9b84..0000000 --- a/libpsi/src/maths/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -pub mod complex; -pub mod complex_ops; - -pub mod matrix; -pub mod matrix_ops; - -pub mod numeric_float; -pub mod numeric_int; -pub mod numeric_traits; - -pub mod vector; -pub mod vector_ops; - -pub use complex::*; -pub use matrix::*; -pub use numeric_traits::*; diff --git a/libpsi/src/maths/numeric_float.rs b/libpsi/src/maths/numeric_float.rs deleted file mode 100644 index 3591f24..0000000 --- a/libpsi/src/maths/numeric_float.rs +++ /dev/null @@ -1,65 +0,0 @@ -use super::{Complex, Float}; - -impl Float for f32 { - fn sqrt(self) -> Self { - libm::sqrtf(self) - } - - fn atan2(y: Self, x: Self) -> Self { - libm::atan2f(y, x) - } -} - -impl Float for f64 { - fn sqrt(self) -> Self { - libm::sqrt(self) - } - - fn atan2(y: Self, x: Self) -> Self { - libm::atan2(y, x) - } -} - -impl Float for Complex<f32> { - fn sqrt(self) -> Self { - let r = self.abs(); - let theta = self.phase(); - - let sqrt_r = libm::sqrtf(r); - let sqrt_theta = theta / 2.0; - - Complex::new( - sqrt_r * libm::cosf(sqrt_theta), - sqrt_r * libm::sinf(sqrt_theta), - ) - } - - fn atan2(y: Self, x: Self) -> Self { - Complex::new( - libm::atan2f(y.real, x.real), - libm::atan2f(y.imaginary, x.imaginary), - ) - } -} - -impl Float for Complex<f64> { - fn sqrt(self) -> Self { - let r = self.abs(); - let theta = self.phase(); - - let sqrt_r = libm::sqrt(r); - let sqrt_theta = theta / 2.0; - - Complex::new( - sqrt_r * libm::cos(sqrt_theta), - sqrt_r * libm::sin(sqrt_theta), - ) - } - - fn atan2(y: Self, x: Self) -> Self { - Complex::new( - libm::atan2(y.real, x.real), - libm::atan2(y.imaginary, x.imaginary), - ) - } -} diff --git a/libpsi/src/maths/numeric_int.rs b/libpsi/src/maths/numeric_int.rs deleted file mode 100644 index a9ecec7..0000000 --- a/libpsi/src/maths/numeric_int.rs +++ /dev/null @@ -1,44 +0,0 @@ -use super::{Integer, Numeric}; - -impl Integer for i64 {} -impl Integer for i32 {} - -impl Numeric for i32 { - fn zero() -> Self { - 0 - } - - fn one() -> Self { - 1 - } -} - -impl Numeric for i64 { - fn zero() -> Self { - 0 - } - - fn one() -> Self { - 1 - } -} - -impl Numeric for f32 { - fn zero() -> Self { - 0.0 - } - - fn one() -> Self { - 1.0 - } -} - -impl Numeric for f64 { - fn zero() -> Self { - 0.0 - } - - fn one() -> Self { - 1.0 - } -} diff --git a/libpsi/src/maths/numeric_traits.rs b/libpsi/src/maths/numeric_traits.rs deleted file mode 100644 index dd7fdec..0000000 --- a/libpsi/src/maths/numeric_traits.rs +++ /dev/null @@ -1,24 +0,0 @@ -use core::ops; - -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; -} - -pub trait Integer: Numeric {} -pub trait Float: Numeric { - fn sqrt(self) -> Self; - fn atan2(y: Self, x: Self) -> Self; -} diff --git a/libpsi/src/maths/vector.rs b/libpsi/src/maths/vector.rs deleted file mode 100644 index 07ff7fb..0000000 --- a/libpsi/src/maths/vector.rs +++ /dev/null @@ -1,268 +0,0 @@ -use super::{Float, Matrix}; -use core::{fmt, ops}; - -#[macro_export] -macro_rules! row_vector { - ($($x:expr),*) => { - RowVector::new(vec![$($x),*]) - }; - ($($x:expr,)*) => { - RowVector::new(vec![$($x),*]) - }; -} - -#[macro_export] -macro_rules! column_vector { - ($($x:expr),*) => { - ColumnVector::new(vec![$($x),*]) - }; - ($($x:expr,)*) => { - ColumnVector::new(vec![$($x),*]) - }; -} - -pub trait Vector<T: Float> { - fn new(data: Vec<T>) -> Self; - fn get(&self, index: usize) -> T; - fn set(&mut self, index: usize, value: T); - fn size(&self) -> usize; - - fn dot(&self, other: &Self) -> T; - fn norm(&self) -> T; - - fn max(&self) -> T; - fn min(&self) -> T; - fn sum(&self) -> T; -} - -pub trait VectorMatrix<T: Float> { - fn from_matrix(matrix: &Matrix<T>) -> Self; - fn to_matrix(&self) -> Matrix<T>; -} - -#[derive(Clone)] -pub struct VectorImpl<T: Float, const ROWS: usize, const COLS: usize>(Vec<T>); -pub type RowVector<T> = VectorImpl<T, 1, 0>; -pub type ColumnVector<T> = VectorImpl<T, 0, 1>; - -impl<T: Float> ColumnVector<T> { - pub fn mul_matrix(&self, matrix: &Matrix<T>) -> Option<ColumnVector<T>> { - if matrix.cols != self.size() { - return None; - } - - let mut result = ColumnVector::new(vec![T::zero(); matrix.rows]); - - for i in 0..matrix.rows { - let mut sum = T::zero(); - for j in 0..matrix.cols { - sum = sum + (matrix.get(i, j) * self.get(j)); - } - result.set(i, sum); - } - - Some(result) - } - - pub fn transpose(&self) -> RowVector<T> { - RowVector::new(self.0.clone()) - } -} - -impl<T: Float> RowVector<T> { - pub fn mul_matrix(&self, matrix: &Matrix<T>) -> Option<RowVector<T>> { - if self.size() != matrix.rows { - return None; - } - - let mut result = RowVector::new(vec![T::zero(); matrix.cols]); - - for j in 0..matrix.cols { - let mut sum = T::zero(); - for i in 0..matrix.rows { - sum = sum + (self.get(i) * matrix.get(i, j)); - } - result.set(j, sum); - } - - Some(result) - } - - pub fn transpose(&self) -> ColumnVector<T> { - ColumnVector::new(self.0.clone()) - } -} - -impl<T: Float> VectorMatrix<T> for RowVector<T> { - fn to_matrix(&self) -> Matrix<T> { - Matrix::new(1, self.size(), self.0.clone()) - } - - fn from_matrix(matrix: &Matrix<T>) -> Self { - Self::new(matrix.data.clone()) - } -} - -impl<T: Float> VectorMatrix<T> for ColumnVector<T> { - fn to_matrix(&self) -> Matrix<T> { - Matrix::new(self.size(), 1, self.0.clone()) - } - - fn from_matrix(matrix: &Matrix<T>) -> Self { - Self::new(matrix.data.clone()) - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> Vector<T> for VectorImpl<T, ROWS, COLS> { - fn new(data: Vec<T>) -> Self { - Self(data) - } - - fn get(&self, index: usize) -> T { - self.0[index] - } - - fn set(&mut self, index: usize, value: T) { - self.0[index] = value; - } - - fn size(&self) -> usize { - self.0.len() - } - - fn dot(&self, other: &Self) -> T { - self.0 - .iter() - .zip(other.0.iter()) - .map(|(a, b)| *a * *b) - .fold(T::zero(), |acc, x| acc + x) - } - - fn norm(&self) -> T { - self.0 - .iter() - .map(|x| *x * *x) - .fold(T::zero(), |acc, x| acc + x) - .sqrt() - } - - fn max(&self) -> T { - *self - .0 - .iter() - .max_by(|a, b| a.partial_cmp(b).unwrap()) - .unwrap_or(&T::zero()) - } - - fn min(&self) -> T { - *self - .0 - .iter() - .min_by(|a, b| a.partial_cmp(b).unwrap()) - .unwrap_or(&T::zero()) - } - - fn sum(&self) -> T { - self.0.iter().fold(T::zero(), |acc, x| acc + *x) - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> VectorImpl<T, ROWS, COLS> { - pub fn add_to(&self, other: &Self) -> Option<VectorImpl<T, ROWS, COLS>> { - if self.size() != other.size() { - return None; - } - - let mut result = VectorImpl::new(vec![T::zero(); ROWS * COLS]); - - for i in 0..self.size() { - let sum = self.get(i) + other.get(i); - result.set(i, sum); - } - - Some(result) - } - - pub fn subtract(&self, other: &Self) -> Option<VectorImpl<T, ROWS, COLS>> { - if self.size() != other.size() { - return None; - } - - let mut result = VectorImpl::new(vec![T::zero(); ROWS * COLS]); - - for i in 0..self.size() { - let sum = self.get(i) - other.get(i); - result.set(i, sum); - } - - Some(result) - } - - pub fn scale(&self, scalar: T) -> VectorImpl<T, ROWS, COLS> { - let mut result = VectorImpl::new(vec![T::zero(); ROWS * COLS]); - - for i in 0..self.size() { - let product = self.get(i) * scalar; - result.set(i, product); - } - - result - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> ops::Index<usize> - for VectorImpl<T, ROWS, COLS> -{ - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self.0[index] - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> ops::IndexMut<usize> - for VectorImpl<T, ROWS, COLS> -{ - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.0[index] - } -} - -impl<T: Float + fmt::Debug> fmt::Debug for RowVector<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "RowVector({:?})", self.0) - } -} - -impl<T: Float + fmt::Debug> fmt::Debug for ColumnVector<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ColumnVector({:?})", self.0) - } -} - -impl<T: Float + fmt::Display> fmt::Display for RowVector<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "[{}]", - self.0 - .iter() - .map(|x| x.to_string()) - .collect::<Vec<String>>() - .join(", ") - ) - } -} - -impl<T: Float + fmt::Display> fmt::Display for ColumnVector<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "[")?; - for (i, x) in self.0.iter().enumerate() { - if i > 0 { - write!(f, ",\n ")?; - } - write!(f, "{}", x)?; - } - write!(f, "]") - } -} diff --git a/libpsi/src/maths/vector_ops.rs b/libpsi/src/maths/vector_ops.rs deleted file mode 100644 index 1e7148c..0000000 --- a/libpsi/src/maths/vector_ops.rs +++ /dev/null @@ -1,107 +0,0 @@ -use super::{Float, Matrix}; -use crate::{ColumnVector, RowVector, VectorImpl}; -use core::ops; - -impl<T: Float, const ROWS: usize, const COLS: usize> ops::Add<&VectorImpl<T, ROWS, COLS>> - for VectorImpl<T, ROWS, COLS> -{ - type Output = Option<VectorImpl<T, ROWS, COLS>>; - - fn add(self, other: &VectorImpl<T, ROWS, COLS>) -> Self::Output { - self.add_to(other) - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> ops::Sub<&VectorImpl<T, ROWS, COLS>> - for VectorImpl<T, ROWS, COLS> -{ - type Output = Option<VectorImpl<T, ROWS, COLS>>; - - fn sub(self, other: &VectorImpl<T, ROWS, COLS>) -> Self::Output { - self.subtract(other) - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> ops::Mul<T> for VectorImpl<T, ROWS, COLS> { - type Output = VectorImpl<T, ROWS, COLS>; - - fn mul(self, scalar: T) -> Self::Output { - self.scale(scalar) - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> ops::Div<T> for VectorImpl<T, ROWS, COLS> { - type Output = VectorImpl<T, ROWS, COLS>; - - fn div(self, scalar: T) -> Self::Output { - self.scale(T::one() / scalar) - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> ops::AddAssign<VectorImpl<T, ROWS, COLS>> - for VectorImpl<T, ROWS, COLS> -{ - fn add_assign(&mut self, other: VectorImpl<T, ROWS, COLS>) { - if let Some(result) = self.add_to(&other) { - *self = result; - } - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> ops::SubAssign<VectorImpl<T, ROWS, COLS>> - for VectorImpl<T, ROWS, COLS> -{ - fn sub_assign(&mut self, other: VectorImpl<T, ROWS, COLS>) { - if let Some(result) = self.subtract(&other) { - *self = result; - } - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> ops::MulAssign<T> - for VectorImpl<T, ROWS, COLS> -{ - fn mul_assign(&mut self, scalar: T) { - *self = self.scale(scalar); - } -} - -impl<T: Float, const ROWS: usize, const COLS: usize> ops::DivAssign<T> - for VectorImpl<T, ROWS, COLS> -{ - fn div_assign(&mut self, scalar: T) { - *self = self.scale(T::one() / scalar); - } -} - -impl<T: Float> ops::Mul<&Matrix<T>> for RowVector<T> { - type Output = Option<RowVector<T>>; - - fn mul(self, matrix: &Matrix<T>) -> Self::Output { - self.mul_matrix(matrix) - } -} - -impl<T: Float> ops::Mul<&Matrix<T>> for ColumnVector<T> { - type Output = Option<ColumnVector<T>>; - - fn mul(self, matrix: &Matrix<T>) -> Self::Output { - self.mul_matrix(matrix) - } -} - -impl<T: Float> ops::MulAssign<&Matrix<T>> for RowVector<T> { - fn mul_assign(&mut self, matrix: &Matrix<T>) { - if let Some(result) = self.mul_matrix(matrix) { - *self = result; - } - } -} - -impl<T: Float> ops::MulAssign<&Matrix<T>> for ColumnVector<T> { - fn mul_assign(&mut self, matrix: &Matrix<T>) { - if let Some(result) = self.mul_matrix(matrix) { - *self = result; - } - } -} |
