aboutsummaryrefslogtreecommitdiff
path: root/libmu/src
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2024-09-22 10:11:02 +0200
committerhachem <im@hachem.wtf>2024-09-22 10:11:02 +0200
commit53287a755cc8bcef8b4c1324f1ed1f34224e15c4 (patch)
tree145974cff606e06c48dfe1ca2476f21d0ce5a1d2 /libmu/src
parenta84b6394209e37620e45155a25b3755b38ba8515 (diff)
rename project to psi
Diffstat (limited to 'libmu/src')
-rw-r--r--libmu/src/core/component.rs51
-rw-r--r--libmu/src/core/mod.rs1
-rw-r--r--libmu/src/lib.rs9
-rw-r--r--libmu/src/maths/complex.rs219
-rw-r--r--libmu/src/maths/matrix.rs245
-rw-r--r--libmu/src/maths/mod.rs8
-rw-r--r--libmu/src/maths/numeric_types.rs152
-rw-r--r--libmu/src/maths/vector.rs374
8 files changed, 0 insertions, 1059 deletions
diff --git a/libmu/src/core/component.rs b/libmu/src/core/component.rs
deleted file mode 100644
index bd18b52..0000000
--- a/libmu/src/core/component.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-use crate::{ColumnVector, Complex, Matrix, VectorMatrix};
-
-pub type QuantumRegister = ColumnVector<Complex<f64>>;
-pub type QuantumBit = ColumnVector<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 bits: [QuantumBit; N] = [$($bit),*];
- QuantumRegister::from(&bits)
- }
- };
-}
-
-impl QuantumBit {
- pub fn get_state(&self) -> i32 {
- (self[1] != Complex::new(0.0, 0.0)) as i32
- }
-}
-
-impl QuantumRegister {
- pub fn from(bits: &[QuantumBit]) -> QuantumRegister {
- let matrices: Vec<Matrix<Complex<f64>>> = bits.iter().map(|bit| bit.to_matrix()).collect();
- let mut result = matrices[0].clone();
- for matrix in &matrices[1..] {
- result = result.kronecker(matrix);
- }
- ColumnVector::from_matrix(&result)
- }
-}
diff --git a/libmu/src/core/mod.rs b/libmu/src/core/mod.rs
deleted file mode 100644
index 9cea807..0000000
--- a/libmu/src/core/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod component;
diff --git a/libmu/src/lib.rs b/libmu/src/lib.rs
deleted file mode 100644
index 9cbd644..0000000
--- a/libmu/src/lib.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-mod core;
-mod maths;
-
-pub use maths::complex::*;
-pub use maths::matrix::*;
-pub use maths::numeric_types::*;
-pub use maths::vector::*;
-
-pub use core::component::*;
diff --git a/libmu/src/maths/complex.rs b/libmu/src/maths/complex.rs
deleted file mode 100644
index 28a3121..0000000
--- a/libmu/src/maths/complex.rs
+++ /dev/null
@@ -1,219 +0,0 @@
-use crate::Float;
-use core::{fmt, ops};
-
-#[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<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())
- }
-}
-
-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> 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,
- }
- }
-}
-
-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,
- }
- }
-}
-
-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;
- }
-}
-
-impl<T: Float> ops::AddAssign<T> for Complex<T> {
- fn add_assign(&mut self, other: T) {
- self.real += other;
- }
-}
-
-impl<T: Float> ops::SubAssign<T> for Complex<T> {
- fn sub_assign(&mut self, other: T) {
- self.real -= other;
- }
-}
-
-impl<T: Float> ops::MulAssign<T> for Complex<T> {
- fn mul_assign(&mut self, other: T) {
- self.real *= other;
- self.imaginary *= other;
- }
-}
-
-impl<T: Float> ops::DivAssign<T> for Complex<T> {
- fn div_assign(&mut self, other: T) {
- self.real /= other;
- self.imaginary /= other;
- }
-}
diff --git a/libmu/src/maths/matrix.rs b/libmu/src/maths/matrix.rs
deleted file mode 100644
index 388f858..0000000
--- a/libmu/src/maths/matrix.rs
+++ /dev/null
@@ -1,245 +0,0 @@
-// TODO(Hachem): Refactor
-
-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 {
- for j in 0..self.cols {
- write!(f, "{:>8} ", self.get(i, j))?;
- }
- writeln!(f)?;
- }
- Ok(())
- }
-}
-
-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/libmu/src/maths/mod.rs b/libmu/src/maths/mod.rs
deleted file mode 100644
index 734cfb4..0000000
--- a/libmu/src/maths/mod.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-pub mod complex;
-pub mod matrix;
-pub mod numeric_types;
-pub mod vector;
-
-pub use complex::*;
-pub use matrix::*;
-pub use numeric_types::*;
diff --git a/libmu/src/maths/numeric_types.rs b/libmu/src/maths/numeric_types.rs
deleted file mode 100644
index f1355de..0000000
--- a/libmu/src/maths/numeric_types.rs
+++ /dev/null
@@ -1,152 +0,0 @@
-use super::Complex;
-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;
-}
-
-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),
- )
- }
-}
-
-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
- }
-}
-
-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)
- }
-}
diff --git a/libmu/src/maths/vector.rs b/libmu/src/maths/vector.rs
deleted file mode 100644
index 0c13e4c..0000000
--- a/libmu/src/maths/vector.rs
+++ /dev/null
@@ -1,374 +0,0 @@
-// TODO(Hachem): Operators Matrix/Vector don't work
-// TODO(Hachem): Refactor
-
-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>;
-}
-
-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, 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, 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> 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> 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;
- }
- }
-}
-
-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, "]")
- }
-}