From 867dcdf978e98f6c92d84d00314994648cca5f3c Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Tue, 24 Feb 2026 20:20:37 +0100 Subject: [PATCH 01/21] add new feature for faer version 0.24 --- .github/workflows/ci.yml | 2 ++ crates/argmin-math/Cargo.toml | 5 ++++- crates/argmin-math/src/faer_tests/test_helper.rs | 2 ++ crates/argmin-math/src/lib.rs | 6 ++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index faa0e833b..d2b58367e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -143,6 +143,8 @@ jobs: # faer - name: argmin-math (faer_latest) run: cargo test -p argmin-math --no-default-features --features "faer_latest" + - name: argmin-math (faer_v0_24) + run: cargo test -p argmin-math --no-default-features --features "faer_v0_24" - name: argmin-math (faer_v0_23) run: cargo test -p argmin-math --no-default-features --features "faer_v0_23" - name: argmin-math (faer_v0_22) diff --git a/crates/argmin-math/Cargo.toml b/crates/argmin-math/Cargo.toml index 5d316556b..cef39b733 100644 --- a/crates/argmin-math/Cargo.toml +++ b/crates/argmin-math/Cargo.toml @@ -38,9 +38,11 @@ faer_0_20 = { package = "faer", version = "0.20", optional = true} faer_0_21 = { package = "faer", version = "0.21", optional = true} faer_0_22 = { package = "faer", version = "0.22", optional = true} faer_0_23 = { package = "faer", version = "0.23", optional = true} +faer_0_24 = { package = "faer", version = "0.24", optional = true} faer_traits_0_21 = {package = "faer-traits", version = "0.21", optional = true} faer_traits_0_22 = {package = "faer-traits", version = "0.22", optional = true} faer_traits_0_23 = {package = "faer-traits", version = "0.23", optional = true} +faer_traits_0_24 = {package = "faer-traits", version = "0.24", optional = true} # general num-complex_0_4 = { package = "num-complex", version = "0.4", optional = true, default-features = false, features = ["std"] } @@ -84,11 +86,12 @@ ndarray_latest = ["ndarray_v0_16"] #faer faer_all = ["primitives"] -faer_latest = ["faer_v0_23"] +faer_latest = ["faer_v0_24"] faer_v0_20 = ["faer_0_20", "num-complex_0_4", "faer_all"] faer_v0_21 = ["faer_0_21", "num-complex_0_4", "faer_traits_0_21", "faer_all"] faer_v0_22 = ["faer_0_22", "num-complex_0_4", "faer_traits_0_22", "faer_all"] faer_v0_23 = ["faer_0_23", "num-complex_0_4", "faer_traits_0_23", "faer_all"] +faer_v0_24 = ["faer_0_24", "num-complex_0_4", "faer_traits_0_24", "faer_all"] ## With `ndarray-linalg` ndarray_v0_16 = ["ndarray_0_16", "ndarray-linalg_0_17", "num-complex_0_4", "ndarray_all"] diff --git a/crates/argmin-math/src/faer_tests/test_helper.rs b/crates/argmin-math/src/faer_tests/test_helper.rs index 56ff0aec1..404590ddb 100644 --- a/crates/argmin-math/src/faer_tests/test_helper.rs +++ b/crates/argmin-math/src/faer_tests/test_helper.rs @@ -9,6 +9,8 @@ cfg_if::cfg_if! { use faer_traits::ComplexField; } else if #[cfg(feature = "faer_v0_23")] { use faer_traits::ComplexField; + } else if #[cfg(feature = "faer_v0_24")] { + use faer_traits::ComplexField; } } diff --git a/crates/argmin-math/src/lib.rs b/crates/argmin-math/src/lib.rs index b63080bea..76a3f4c4b 100644 --- a/crates/argmin-math/src/lib.rs +++ b/crates/argmin-math/src/lib.rs @@ -270,6 +270,8 @@ cfg_if::cfg_if! { extern crate faer_0_22 as faer; } else if #[cfg(feature = "faer_v0_23")] { extern crate faer_0_23 as faer; + } else if #[cfg(feature = "faer_v0_24")] { + extern crate faer_0_24 as faer; } } @@ -315,6 +317,10 @@ cfg_if! { extern crate faer_traits_0_23 as faer_traits; mod faer_m_0_21; use faer_m_0_21 as faer_m; + } else if #[cfg(feature = "faer_v0_24")] { + extern crate faer_traits_0_24 as faer_traits; + mod faer_m_0_21; + use faer_m_0_21 as faer_m; } } From da05274df92805302f3654e981452f15f70ed27c Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Tue, 24 Feb 2026 20:26:05 +0100 Subject: [PATCH 02/21] fix tests --- crates/argmin-math/src/faer_m_0_21/add.rs | 2 +- crates/argmin-math/src/faer_m_0_21/mul.rs | 2 +- crates/argmin-math/src/faer_m_0_21/sub.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/argmin-math/src/faer_m_0_21/add.rs b/crates/argmin-math/src/faer_m_0_21/add.rs index 460c6b981..3cd0789ea 100644 --- a/crates/argmin-math/src/faer_m_0_21/add.rs +++ b/crates/argmin-math/src/faer_m_0_21/add.rs @@ -4,7 +4,7 @@ use faer::{ reborrow::{IntoConst, Reborrow, ReborrowMut}, unzip, zip, Mat, MatMut, MatRef, }; -use faer_traits::ComplexField; +use faer_traits::{AddByRef, ComplexField}; use std::ops::{Add, AddAssign}; /// MatRef + Scalar -> Mat diff --git a/crates/argmin-math/src/faer_m_0_21/mul.rs b/crates/argmin-math/src/faer_m_0_21/mul.rs index 9a0670200..288d4831b 100644 --- a/crates/argmin-math/src/faer_m_0_21/mul.rs +++ b/crates/argmin-math/src/faer_m_0_21/mul.rs @@ -4,7 +4,7 @@ use faer::{ reborrow::{IntoConst, Reborrow, ReborrowMut}, Mat, MatMut, MatRef, }; -use faer_traits::ComplexField; +use faer_traits::{ComplexField, MulByRef}; use std::ops::Mul; /// MatRef * Scalar -> Mat diff --git a/crates/argmin-math/src/faer_m_0_21/sub.rs b/crates/argmin-math/src/faer_m_0_21/sub.rs index ccd6f4c63..fc80bb008 100644 --- a/crates/argmin-math/src/faer_m_0_21/sub.rs +++ b/crates/argmin-math/src/faer_m_0_21/sub.rs @@ -4,7 +4,7 @@ use faer::{ reborrow::{IntoConst, Reborrow, ReborrowMut}, unzip, zip, Mat, MatMut, MatRef, }; -use faer_traits::{ComplexField, Conjugate}; +use faer_traits::{ComplexField, Conjugate, SubByRef}; use std::ops::{Sub, SubAssign}; /// MatRef / Scalar -> MatRef From ca7a9f1b240cc13b4c70c442ec6a34d4b5e17bb1 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Thu, 18 Dec 2025 10:03:32 +0100 Subject: [PATCH 03/21] implement some traits needed for solver --- crates/argmin-math/src/faer_m_0_21/dot.rs | 43 +++++++++++++++++++- crates/argmin-math/src/faer_m_0_21/l2norm.rs | 14 ++++++- crates/argmin-math/src/faer_m_0_21/mul.rs | 21 +++++++++- crates/argmin-math/src/faer_m_0_21/sub.rs | 18 +++++++- 4 files changed, 92 insertions(+), 4 deletions(-) diff --git a/crates/argmin-math/src/faer_m_0_21/dot.rs b/crates/argmin-math/src/faer_m_0_21/dot.rs index 34342c297..bab1dee9e 100644 --- a/crates/argmin-math/src/faer_m_0_21/dot.rs +++ b/crates/argmin-math/src/faer_m_0_21/dot.rs @@ -1,5 +1,5 @@ use crate::ArgminDot; -use faer::{mat::AsMatRef, Mat, MatRef}; +use faer::{mat::AsMatRef, Col, ColRef, Mat, MatRef}; use faer_traits::ComplexField; use std::ops::Mul; @@ -47,6 +47,26 @@ mod matrix_matrix_multiplication { } } +mod matrix_column_multiplication { + use super::*; + + /// MatRef . ColRef -> Col + impl ArgminDot, Col> for MatRef<'_, E> { + #[inline] + fn dot(&self, other: &ColRef<'_, E>) -> Col { + self * other + } + } + + /// Mat . Col -> Col + impl ArgminDot, Col> for Mat { + #[inline] + fn dot(&self, other: &Col) -> Col { + <_ as ArgminDot<_, _>>::dot(&self.as_mat_ref(), &other.as_ref()) + } + } +} + /// contains implementations for the scalar product of two column vectors of /// the same length. This is v^H . u for two column vectors v,u. //@note(geo-ant) the corresponding nalgebra implementations allow taking a scalar @@ -107,6 +127,27 @@ mod scalar_product { <_ as ArgminDot<_, _>>::dot(&self.as_mat_ref(), &other.as_mat_ref()) } } + + /// ColRef . ColRef -> Col + impl> ArgminDot, E> for ColRef<'_, E> { + #[inline] + fn dot(&self, other: &ColRef<'_, E>) -> E { + assert_eq!( + self.nrows(), + other.nrows(), + "vectors for dot product must have same number of elements" + ); + self.conjugate().transpose() * other + } + } + + /// Col . Col -> Col + impl> ArgminDot, E> for Col { + #[inline] + fn dot(&self, other: &Col) -> E { + <_ as ArgminDot<_, _>>::dot(&self.as_ref(), &other.as_ref()) + } + } } //@note(geo) implemented for compatibility with the nalgebra implementations, diff --git a/crates/argmin-math/src/faer_m_0_21/l2norm.rs b/crates/argmin-math/src/faer_m_0_21/l2norm.rs index b5bd100cf..8a9135398 100644 --- a/crates/argmin-math/src/faer_m_0_21/l2norm.rs +++ b/crates/argmin-math/src/faer_m_0_21/l2norm.rs @@ -1,5 +1,5 @@ use crate::ArgminL2Norm; -use faer::{Mat, MatRef}; +use faer::{Col, ColRef, Mat, MatRef}; use faer_traits::ComplexField; impl ArgminL2Norm for MatRef<'_, E> { @@ -13,3 +13,15 @@ impl ArgminL2Norm for Mat { self.norm_l2() } } + +impl ArgminL2Norm for ColRef<'_, E> { + fn l2_norm(&self) -> E::Real { + self.norm_l2() + } +} + +impl ArgminL2Norm for Col { + fn l2_norm(&self) -> E::Real { + self.norm_l2() + } +} diff --git a/crates/argmin-math/src/faer_m_0_21/mul.rs b/crates/argmin-math/src/faer_m_0_21/mul.rs index 288d4831b..00f63e5cd 100644 --- a/crates/argmin-math/src/faer_m_0_21/mul.rs +++ b/crates/argmin-math/src/faer_m_0_21/mul.rs @@ -2,7 +2,7 @@ use crate::ArgminMul; use faer::{ mat::{AsMatMut, AsMatRef}, reborrow::{IntoConst, Reborrow, ReborrowMut}, - Mat, MatMut, MatRef, + unzip, zip, Col, ColMut, ColRef, Mat, MatMut, MatRef, }; use faer_traits::{ComplexField, MulByRef}; use std::ops::Mul; @@ -87,3 +87,22 @@ impl ArgminMul, Mat> for Mat { <_ as ArgminMul<_, _>>::mul(&self.as_mat_ref(), &other.as_mat_ref()) } } + +/// ColRef * ColRef -> Col (pointwise multiplication) +impl ArgminMul, Col> for ColRef<'_, E> { + #[inline] + fn mul(&self, other: &ColRef<'_, E>) -> Col { + let mut result = Col::zeros(self.nrows()); // TODO: why not possible like sub + zip!(&mut result, self, other) + .for_each(|unzip!(result, this, other)| *result = this.mul_by_ref(other)); + result + } +} + +/// Col * Col -> Col (pointwise multiplication) +impl ArgminMul, Col> for Col { + #[inline] + fn mul(&self, other: &Col) -> Col { + <_ as ArgminMul<_, _>>::mul(&self.as_ref(), &other.as_ref()) + } +} diff --git a/crates/argmin-math/src/faer_m_0_21/sub.rs b/crates/argmin-math/src/faer_m_0_21/sub.rs index fc80bb008..f86919b00 100644 --- a/crates/argmin-math/src/faer_m_0_21/sub.rs +++ b/crates/argmin-math/src/faer_m_0_21/sub.rs @@ -2,7 +2,7 @@ use crate::ArgminSub; use faer::{ mat::AsMatRef, reborrow::{IntoConst, Reborrow, ReborrowMut}, - unzip, zip, Mat, MatMut, MatRef, + unzip, zip, Col, ColMut, ColRef, Mat, MatMut, MatRef, }; use faer_traits::{ComplexField, Conjugate, SubByRef}; use std::ops::{Sub, SubAssign}; @@ -90,3 +90,19 @@ impl ArgminSub, Mat> for Mat { <_ as ArgminSub<_, _>>::sub(&self.as_mat_ref(), &other.as_mat_ref()) } } + +/// ColRef / ColRef -> Col +impl ArgminSub, Col> for ColRef<'_, E> { + #[inline] + fn sub(&self, other: &ColRef<'_, E>) -> Col { + zip!(self, other).map(|unzip!(this, other)| this.sub_by_ref(other)) + } +} + +/// Col / Col -> Col +impl ArgminSub, Col> for Col { + #[inline] + fn sub(&self, other: &Col) -> Col { + <_ as ArgminSub<_, _>>::sub(&self.as_ref(), &other.as_ref()) + } +} From 179069d7ccbdc2ab910cdc0b399ab0652984eeb0 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Thu, 18 Dec 2025 10:57:47 +0100 Subject: [PATCH 04/21] add missing trait implementations for multiplying col with scalar values --- crates/argmin-math/src/faer_m_0_21/mul.rs | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/crates/argmin-math/src/faer_m_0_21/mul.rs b/crates/argmin-math/src/faer_m_0_21/mul.rs index 00f63e5cd..dd2246969 100644 --- a/crates/argmin-math/src/faer_m_0_21/mul.rs +++ b/crates/argmin-math/src/faer_m_0_21/mul.rs @@ -106,3 +106,39 @@ impl ArgminMul, Col> for Col { <_ as ArgminMul<_, _>>::mul(&self.as_ref(), &other.as_ref()) } } + +/// E * ColRef -> Col +impl ArgminMul, Col> for E { + #[inline] + fn mul(&self, other: &ColRef<'_, E>) -> Col { + let mut result = Col::zeros(other.nrows()); // TODO: why not possible like sub + zip!(&mut result, other).for_each(|unzip!(result, other)| *result = self.mul_by_ref(other)); + result + } +} + +/// E * Col -> Col +impl ArgminMul, Col> for E { + #[inline] + fn mul(&self, other: &Col) -> Col { + <_ as ArgminMul<_, _>>::mul(self, &other.as_ref()) + } +} + +/// ColRef * E -> Col +impl ArgminMul> for ColRef<'_, E> { + #[inline] + fn mul(&self, other: &E) -> Col { + let mut result = Col::zeros(self.nrows()); // TODO: why not possible like sub + zip!(&mut result, self).for_each(|unzip!(result, self_)| *result = self_.mul_by_ref(other)); + result + } +} + +/// Col * E -> Col +impl ArgminMul> for Col { + #[inline] + fn mul(&self, other: &E) -> Col { + <_ as ArgminMul<_, _>>::mul(&self.as_ref(), other) + } +} From 7173b972dc87c08eb1e45ee186ece1208be1a9be Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Thu, 18 Dec 2025 18:23:18 +0100 Subject: [PATCH 05/21] move col implementations to own module --- crates/argmin-math/src/faer_m_0_21/col/dot.rs | 52 ++++++++++++++++ .../src/faer_m_0_21/col/l2_norm.rs | 15 +++++ crates/argmin-math/src/faer_m_0_21/col/mod.rs | 4 ++ crates/argmin-math/src/faer_m_0_21/col/mul.rs | 59 +++++++++++++++++++ crates/argmin-math/src/faer_m_0_21/col/sub.rs | 20 +++++++ crates/argmin-math/src/faer_m_0_21/dot.rs | 43 +------------- crates/argmin-math/src/faer_m_0_21/l2norm.rs | 14 +---- crates/argmin-math/src/faer_m_0_21/mod.rs | 1 + crates/argmin-math/src/faer_m_0_21/mul.rs | 59 +------------------ crates/argmin-math/src/faer_m_0_21/sub.rs | 22 +------ 10 files changed, 156 insertions(+), 133 deletions(-) create mode 100644 crates/argmin-math/src/faer_m_0_21/col/dot.rs create mode 100644 crates/argmin-math/src/faer_m_0_21/col/l2_norm.rs create mode 100644 crates/argmin-math/src/faer_m_0_21/col/mod.rs create mode 100644 crates/argmin-math/src/faer_m_0_21/col/mul.rs create mode 100644 crates/argmin-math/src/faer_m_0_21/col/sub.rs diff --git a/crates/argmin-math/src/faer_m_0_21/col/dot.rs b/crates/argmin-math/src/faer_m_0_21/col/dot.rs new file mode 100644 index 000000000..9d2423d4a --- /dev/null +++ b/crates/argmin-math/src/faer_m_0_21/col/dot.rs @@ -0,0 +1,52 @@ +use crate::ArgminDot; +use faer::prelude::*; +use faer_traits::ComplexField; + +/// contains implementations for applying matrices to column vectors. +mod matrix_column_multiplication { + use super::*; + + /// MatRef . ColRef -> Col + impl ArgminDot, Col> for MatRef<'_, E> { + #[inline] + fn dot(&self, other: &ColRef<'_, E>) -> Col { + self * other + } + } + + /// Mat . Col -> Col + impl ArgminDot, Col> for Mat { + #[inline] + fn dot(&self, other: &Col) -> Col { + <_ as ArgminDot<_, _>>::dot(&self.as_ref(), &other.as_ref()) + } + } +} + +/// contains implementations for the scalar product of two column vectors of +/// the same length. This is v^H . u for two column vectors v,u. +mod scalar_product { + use super::*; + use faer_traits::Conjugate; + + /// ColRef . ColRef -> Col + impl> ArgminDot, E> for ColRef<'_, E> { + #[inline] + fn dot(&self, other: &ColRef<'_, E>) -> E { + assert_eq!( + self.nrows(), + other.nrows(), + "vectors for dot product must have same number of elements" + ); + self.conjugate().transpose() * other + } + } + + /// Col . Col -> Col + impl> ArgminDot, E> for Col { + #[inline] + fn dot(&self, other: &Col) -> E { + <_ as ArgminDot<_, _>>::dot(&self.as_ref(), &other.as_ref()) + } + } +} diff --git a/crates/argmin-math/src/faer_m_0_21/col/l2_norm.rs b/crates/argmin-math/src/faer_m_0_21/col/l2_norm.rs new file mode 100644 index 000000000..a7f4c8074 --- /dev/null +++ b/crates/argmin-math/src/faer_m_0_21/col/l2_norm.rs @@ -0,0 +1,15 @@ +use crate::ArgminL2Norm; +use faer::{Col, ColRef}; +use faer_traits::ComplexField; + +impl ArgminL2Norm for ColRef<'_, E> { + fn l2_norm(&self) -> E::Real { + self.norm_l2() + } +} + +impl ArgminL2Norm for Col { + fn l2_norm(&self) -> E::Real { + self.norm_l2() + } +} diff --git a/crates/argmin-math/src/faer_m_0_21/col/mod.rs b/crates/argmin-math/src/faer_m_0_21/col/mod.rs new file mode 100644 index 000000000..d25070d28 --- /dev/null +++ b/crates/argmin-math/src/faer_m_0_21/col/mod.rs @@ -0,0 +1,4 @@ +mod dot; +mod l2_norm; +mod mul; +mod sub; diff --git a/crates/argmin-math/src/faer_m_0_21/col/mul.rs b/crates/argmin-math/src/faer_m_0_21/col/mul.rs new file mode 100644 index 000000000..b773beeef --- /dev/null +++ b/crates/argmin-math/src/faer_m_0_21/col/mul.rs @@ -0,0 +1,59 @@ +use crate::ArgminMul; +use faer::{unzip, zip, Col, ColMut, ColRef}; +use faer_traits::{ComplexField, MulByRef}; +use std::ops::Mul; + +/// ColRef * ColRef -> Col (pointwise multiplication) +impl ArgminMul, Col> for ColRef<'_, E> { + #[inline] + fn mul(&self, other: &ColRef<'_, E>) -> Col { + let mut result = Col::zeros(self.nrows()); // TODO: why not possible like sub + zip!(&mut result, self, other) + .for_each(|unzip!(result, this, other)| *result = this.mul_by_ref(other)); + result + } +} + +/// Col * Col -> Col (pointwise multiplication) +impl ArgminMul, Col> for Col { + #[inline] + fn mul(&self, other: &Col) -> Col { + <_ as ArgminMul<_, _>>::mul(&self.as_ref(), &other.as_ref()) + } +} + +/// E * ColRef -> Col +impl ArgminMul, Col> for E { + #[inline] + fn mul(&self, other: &ColRef<'_, E>) -> Col { + let mut result = Col::zeros(other.nrows()); // TODO: why not possible like sub + zip!(&mut result, other).for_each(|unzip!(result, other)| *result = self.mul_by_ref(other)); + result + } +} + +/// E * Col -> Col +impl ArgminMul, Col> for E { + #[inline] + fn mul(&self, other: &Col) -> Col { + <_ as ArgminMul<_, _>>::mul(self, &other.as_ref()) + } +} + +/// ColRef * E -> Col +impl ArgminMul> for ColRef<'_, E> { + #[inline] + fn mul(&self, other: &E) -> Col { + let mut result = Col::zeros(self.nrows()); // TODO: why not possible like sub + zip!(&mut result, self).for_each(|unzip!(result, self_)| *result = self_.mul_by_ref(other)); + result + } +} + +/// Col * E -> Col +impl ArgminMul> for Col { + #[inline] + fn mul(&self, other: &E) -> Col { + <_ as ArgminMul<_, _>>::mul(&self.as_ref(), other) + } +} diff --git a/crates/argmin-math/src/faer_m_0_21/col/sub.rs b/crates/argmin-math/src/faer_m_0_21/col/sub.rs new file mode 100644 index 000000000..ff784673d --- /dev/null +++ b/crates/argmin-math/src/faer_m_0_21/col/sub.rs @@ -0,0 +1,20 @@ +use crate::ArgminSub; +use faer::{unzip, zip, Col, ColMut, ColRef}; +use faer_traits::{ComplexField, Conjugate, SubByRef}; +use std::ops::{Sub, SubAssign}; + +/// ColRef / ColRef -> Col +impl ArgminSub, Col> for ColRef<'_, E> { + #[inline] + fn sub(&self, other: &ColRef<'_, E>) -> Col { + zip!(self, other).map(|unzip!(this, other)| this.sub_by_ref(other)) + } +} + +/// Col / Col -> Col +impl ArgminSub, Col> for Col { + #[inline] + fn sub(&self, other: &Col) -> Col { + <_ as ArgminSub<_, _>>::sub(&self.as_ref(), &other.as_ref()) + } +} diff --git a/crates/argmin-math/src/faer_m_0_21/dot.rs b/crates/argmin-math/src/faer_m_0_21/dot.rs index bab1dee9e..34342c297 100644 --- a/crates/argmin-math/src/faer_m_0_21/dot.rs +++ b/crates/argmin-math/src/faer_m_0_21/dot.rs @@ -1,5 +1,5 @@ use crate::ArgminDot; -use faer::{mat::AsMatRef, Col, ColRef, Mat, MatRef}; +use faer::{mat::AsMatRef, Mat, MatRef}; use faer_traits::ComplexField; use std::ops::Mul; @@ -47,26 +47,6 @@ mod matrix_matrix_multiplication { } } -mod matrix_column_multiplication { - use super::*; - - /// MatRef . ColRef -> Col - impl ArgminDot, Col> for MatRef<'_, E> { - #[inline] - fn dot(&self, other: &ColRef<'_, E>) -> Col { - self * other - } - } - - /// Mat . Col -> Col - impl ArgminDot, Col> for Mat { - #[inline] - fn dot(&self, other: &Col) -> Col { - <_ as ArgminDot<_, _>>::dot(&self.as_mat_ref(), &other.as_ref()) - } - } -} - /// contains implementations for the scalar product of two column vectors of /// the same length. This is v^H . u for two column vectors v,u. //@note(geo-ant) the corresponding nalgebra implementations allow taking a scalar @@ -127,27 +107,6 @@ mod scalar_product { <_ as ArgminDot<_, _>>::dot(&self.as_mat_ref(), &other.as_mat_ref()) } } - - /// ColRef . ColRef -> Col - impl> ArgminDot, E> for ColRef<'_, E> { - #[inline] - fn dot(&self, other: &ColRef<'_, E>) -> E { - assert_eq!( - self.nrows(), - other.nrows(), - "vectors for dot product must have same number of elements" - ); - self.conjugate().transpose() * other - } - } - - /// Col . Col -> Col - impl> ArgminDot, E> for Col { - #[inline] - fn dot(&self, other: &Col) -> E { - <_ as ArgminDot<_, _>>::dot(&self.as_ref(), &other.as_ref()) - } - } } //@note(geo) implemented for compatibility with the nalgebra implementations, diff --git a/crates/argmin-math/src/faer_m_0_21/l2norm.rs b/crates/argmin-math/src/faer_m_0_21/l2norm.rs index 8a9135398..b5bd100cf 100644 --- a/crates/argmin-math/src/faer_m_0_21/l2norm.rs +++ b/crates/argmin-math/src/faer_m_0_21/l2norm.rs @@ -1,5 +1,5 @@ use crate::ArgminL2Norm; -use faer::{Col, ColRef, Mat, MatRef}; +use faer::{Mat, MatRef}; use faer_traits::ComplexField; impl ArgminL2Norm for MatRef<'_, E> { @@ -13,15 +13,3 @@ impl ArgminL2Norm for Mat { self.norm_l2() } } - -impl ArgminL2Norm for ColRef<'_, E> { - fn l2_norm(&self) -> E::Real { - self.norm_l2() - } -} - -impl ArgminL2Norm for Col { - fn l2_norm(&self) -> E::Real { - self.norm_l2() - } -} diff --git a/crates/argmin-math/src/faer_m_0_21/mod.rs b/crates/argmin-math/src/faer_m_0_21/mod.rs index 651c8654a..857d75288 100644 --- a/crates/argmin-math/src/faer_m_0_21/mod.rs +++ b/crates/argmin-math/src/faer_m_0_21/mod.rs @@ -8,6 +8,7 @@ #![allow(unused_imports)] mod add; +mod col; mod conj; mod div; mod dot; diff --git a/crates/argmin-math/src/faer_m_0_21/mul.rs b/crates/argmin-math/src/faer_m_0_21/mul.rs index dd2246969..0d0ba1f18 100644 --- a/crates/argmin-math/src/faer_m_0_21/mul.rs +++ b/crates/argmin-math/src/faer_m_0_21/mul.rs @@ -1,8 +1,8 @@ use crate::ArgminMul; use faer::{ - mat::{AsMatMut, AsMatRef}, + mat::AsMatRef, reborrow::{IntoConst, Reborrow, ReborrowMut}, - unzip, zip, Col, ColMut, ColRef, Mat, MatMut, MatRef, + unzip, zip, Mat, MatRef, }; use faer_traits::{ComplexField, MulByRef}; use std::ops::Mul; @@ -87,58 +87,3 @@ impl ArgminMul, Mat> for Mat { <_ as ArgminMul<_, _>>::mul(&self.as_mat_ref(), &other.as_mat_ref()) } } - -/// ColRef * ColRef -> Col (pointwise multiplication) -impl ArgminMul, Col> for ColRef<'_, E> { - #[inline] - fn mul(&self, other: &ColRef<'_, E>) -> Col { - let mut result = Col::zeros(self.nrows()); // TODO: why not possible like sub - zip!(&mut result, self, other) - .for_each(|unzip!(result, this, other)| *result = this.mul_by_ref(other)); - result - } -} - -/// Col * Col -> Col (pointwise multiplication) -impl ArgminMul, Col> for Col { - #[inline] - fn mul(&self, other: &Col) -> Col { - <_ as ArgminMul<_, _>>::mul(&self.as_ref(), &other.as_ref()) - } -} - -/// E * ColRef -> Col -impl ArgminMul, Col> for E { - #[inline] - fn mul(&self, other: &ColRef<'_, E>) -> Col { - let mut result = Col::zeros(other.nrows()); // TODO: why not possible like sub - zip!(&mut result, other).for_each(|unzip!(result, other)| *result = self.mul_by_ref(other)); - result - } -} - -/// E * Col -> Col -impl ArgminMul, Col> for E { - #[inline] - fn mul(&self, other: &Col) -> Col { - <_ as ArgminMul<_, _>>::mul(self, &other.as_ref()) - } -} - -/// ColRef * E -> Col -impl ArgminMul> for ColRef<'_, E> { - #[inline] - fn mul(&self, other: &E) -> Col { - let mut result = Col::zeros(self.nrows()); // TODO: why not possible like sub - zip!(&mut result, self).for_each(|unzip!(result, self_)| *result = self_.mul_by_ref(other)); - result - } -} - -/// Col * E -> Col -impl ArgminMul> for Col { - #[inline] - fn mul(&self, other: &E) -> Col { - <_ as ArgminMul<_, _>>::mul(&self.as_ref(), other) - } -} diff --git a/crates/argmin-math/src/faer_m_0_21/sub.rs b/crates/argmin-math/src/faer_m_0_21/sub.rs index f86919b00..cade8542b 100644 --- a/crates/argmin-math/src/faer_m_0_21/sub.rs +++ b/crates/argmin-math/src/faer_m_0_21/sub.rs @@ -1,9 +1,5 @@ use crate::ArgminSub; -use faer::{ - mat::AsMatRef, - reborrow::{IntoConst, Reborrow, ReborrowMut}, - unzip, zip, Col, ColMut, ColRef, Mat, MatMut, MatRef, -}; +use faer::{mat::AsMatRef, unzip, zip, Mat, MatRef}; use faer_traits::{ComplexField, Conjugate, SubByRef}; use std::ops::{Sub, SubAssign}; @@ -90,19 +86,3 @@ impl ArgminSub, Mat> for Mat { <_ as ArgminSub<_, _>>::sub(&self.as_mat_ref(), &other.as_mat_ref()) } } - -/// ColRef / ColRef -> Col -impl ArgminSub, Col> for ColRef<'_, E> { - #[inline] - fn sub(&self, other: &ColRef<'_, E>) -> Col { - zip!(self, other).map(|unzip!(this, other)| this.sub_by_ref(other)) - } -} - -/// Col / Col -> Col -impl ArgminSub, Col> for Col { - #[inline] - fn sub(&self, other: &Col) -> Col { - <_ as ArgminSub<_, _>>::sub(&self.as_ref(), &other.as_ref()) - } -} From 15ad60eaf5ac0491e8dbfc10540f0b89be469f2d Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Thu, 18 Dec 2025 18:36:08 +0100 Subject: [PATCH 06/21] complete sub --- crates/argmin-math/Cargo.toml | 2 +- crates/argmin-math/src/faer_m_0_21/col/sub.rs | 43 +++++++++++++++++++ crates/argmin-math/src/faer_m_0_21/sub.rs | 2 +- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/crates/argmin-math/Cargo.toml b/crates/argmin-math/Cargo.toml index cef39b733..670f855a0 100644 --- a/crates/argmin-math/Cargo.toml +++ b/crates/argmin-math/Cargo.toml @@ -61,7 +61,7 @@ paste = "1" approx = "0.5.0" [features] -default = ["primitives", "vec", "rand"] +default = ["primitives", "vec", "rand", "faer_v0_23"] latest_all = ["primitives", "vec", "rand", "nalgebra_latest", "ndarray_latest"] # primitives diff --git a/crates/argmin-math/src/faer_m_0_21/col/sub.rs b/crates/argmin-math/src/faer_m_0_21/col/sub.rs index ff784673d..6a736d980 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/sub.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/sub.rs @@ -3,6 +3,33 @@ use faer::{unzip, zip, Col, ColMut, ColRef}; use faer_traits::{ComplexField, Conjugate, SubByRef}; use std::ops::{Sub, SubAssign}; +/// ColRef / Scalar -> Col +impl ArgminSub> for ColRef<'_, E> { + #[inline] + fn sub(&self, other: &E) -> Col { + zip!(self).map(|unzip!(this)| this.sub_by_ref(other)) + } +} + +/// Col / Scalar -> Col +impl ArgminSub> for Col { + #[inline] + fn sub(&self, other: &E) -> Col { + <_ as ArgminSub<_, _>>::sub(&self.as_ref(), other) + } +} + +/// Scalar / ColRef -> Col +impl<'a, E> ArgminSub, Col> for E +where + E: ComplexField, +{ + #[inline] + fn sub(&self, other: &ColRef<'a, E>) -> Col { + zip!(other).map(|unzip!(other)| self.sub_by_ref(other)) + } +} + /// ColRef / ColRef -> Col impl ArgminSub, Col> for ColRef<'_, E> { #[inline] @@ -11,6 +38,22 @@ impl ArgminSub, Col> for ColRef<'_, E> { } } +/// Col / ColRef -> Col +impl ArgminSub, Col> for Col { + #[inline] + fn sub(&self, other: &ColRef<'_, E>) -> Col { + <_ as ArgminSub<_, _>>::sub(&self.as_ref(), other) + } +} + +/// ColRef / Col -> Col +impl ArgminSub, Col> for ColRef<'_, E> { + #[inline] + fn sub(&self, other: &Col) -> Col { + <_ as ArgminSub<_, _>>::sub(self, &other.as_ref()) + } +} + /// Col / Col -> Col impl ArgminSub, Col> for Col { #[inline] diff --git a/crates/argmin-math/src/faer_m_0_21/sub.rs b/crates/argmin-math/src/faer_m_0_21/sub.rs index cade8542b..778433e5b 100644 --- a/crates/argmin-math/src/faer_m_0_21/sub.rs +++ b/crates/argmin-math/src/faer_m_0_21/sub.rs @@ -3,7 +3,7 @@ use faer::{mat::AsMatRef, unzip, zip, Mat, MatRef}; use faer_traits::{ComplexField, Conjugate, SubByRef}; use std::ops::{Sub, SubAssign}; -/// MatRef / Scalar -> MatRef +/// MatRef / Scalar -> Mat impl ArgminSub> for MatRef<'_, E> where E: ComplexField, From 9ef156d604b9ee76775f33432ef52af5eb598017 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Thu, 18 Dec 2025 21:21:52 +0100 Subject: [PATCH 07/21] complete other trait implementations --- crates/argmin-math/src/faer_m_0_21/add.rs | 2 - crates/argmin-math/src/faer_m_0_21/col/dot.rs | 32 +++++++++++++ crates/argmin-math/src/faer_m_0_21/col/mul.rs | 47 +++++++++---------- crates/argmin-math/src/faer_m_0_21/col/sub.rs | 11 ++++- crates/argmin-math/src/faer_m_0_21/sub.rs | 1 - 5 files changed, 65 insertions(+), 28 deletions(-) diff --git a/crates/argmin-math/src/faer_m_0_21/add.rs b/crates/argmin-math/src/faer_m_0_21/add.rs index 3cd0789ea..4b31d159b 100644 --- a/crates/argmin-math/src/faer_m_0_21/add.rs +++ b/crates/argmin-math/src/faer_m_0_21/add.rs @@ -1,11 +1,9 @@ use crate::ArgminAdd; use faer::{ mat::{AsMatMut, AsMatRef}, - reborrow::{IntoConst, Reborrow, ReborrowMut}, unzip, zip, Mat, MatMut, MatRef, }; use faer_traits::{AddByRef, ComplexField}; -use std::ops::{Add, AddAssign}; /// MatRef + Scalar -> Mat impl ArgminAdd> for MatRef<'_, E, R, C> diff --git a/crates/argmin-math/src/faer_m_0_21/col/dot.rs b/crates/argmin-math/src/faer_m_0_21/col/dot.rs index 9d2423d4a..f92866951 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/dot.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/dot.rs @@ -14,6 +14,22 @@ mod matrix_column_multiplication { } } + /// Mat . ColRef -> Col + impl ArgminDot, Col> for Mat { + #[inline] + fn dot(&self, other: &ColRef<'_, E>) -> Col { + <_ as ArgminDot<_, _>>::dot(&self.as_ref(), other) + } + } + + /// MatRef . ColRef -> Col + impl ArgminDot, Col> for MatRef<'_, E> { + #[inline] + fn dot(&self, other: &Col) -> Col { + <_ as ArgminDot<_, _>>::dot(self, &other.as_ref()) + } + } + /// Mat . Col -> Col impl ArgminDot, Col> for Mat { #[inline] @@ -42,6 +58,22 @@ mod scalar_product { } } + /// Col . ColRef -> Col + impl> ArgminDot, E> for Col { + #[inline] + fn dot(&self, other: &ColRef<'_, E>) -> E { + <_ as ArgminDot<_, _>>::dot(&self.as_ref(), other) + } + } + + /// ColRef . Col -> Col + impl> ArgminDot, E> for ColRef<'_, E> { + #[inline] + fn dot(&self, other: &Col) -> E { + <_ as ArgminDot<_, _>>::dot(self, &other.as_ref()) + } + } + /// Col . Col -> Col impl> ArgminDot, E> for Col { #[inline] diff --git a/crates/argmin-math/src/faer_m_0_21/col/mul.rs b/crates/argmin-math/src/faer_m_0_21/col/mul.rs index b773beeef..599372ba7 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/mul.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/mul.rs @@ -1,28 +1,18 @@ use crate::ArgminMul; use faer::{unzip, zip, Col, ColMut, ColRef}; use faer_traits::{ComplexField, MulByRef}; -use std::ops::Mul; -/// ColRef * ColRef -> Col (pointwise multiplication) -impl ArgminMul, Col> for ColRef<'_, E> { +/// ColRef * Scalar -> Col +impl ArgminMul> for ColRef<'_, E> { #[inline] - fn mul(&self, other: &ColRef<'_, E>) -> Col { + fn mul(&self, other: &E) -> Col { let mut result = Col::zeros(self.nrows()); // TODO: why not possible like sub - zip!(&mut result, self, other) - .for_each(|unzip!(result, this, other)| *result = this.mul_by_ref(other)); + zip!(&mut result, self).for_each(|unzip!(result, self_)| *result = self_.mul_by_ref(other)); result } } -/// Col * Col -> Col (pointwise multiplication) -impl ArgminMul, Col> for Col { - #[inline] - fn mul(&self, other: &Col) -> Col { - <_ as ArgminMul<_, _>>::mul(&self.as_ref(), &other.as_ref()) - } -} - -/// E * ColRef -> Col +/// Scalar * ColRef -> Col impl ArgminMul, Col> for E { #[inline] fn mul(&self, other: &ColRef<'_, E>) -> Col { @@ -32,7 +22,15 @@ impl ArgminMul, Col> for E { } } -/// E * Col -> Col +/// Col * Scalar -> Col +impl ArgminMul> for Col { + #[inline] + fn mul(&self, other: &E) -> Col { + <_ as ArgminMul<_, _>>::mul(&self.as_ref(), other) + } +} + +/// Scalar * Col -> Col impl ArgminMul, Col> for E { #[inline] fn mul(&self, other: &Col) -> Col { @@ -40,20 +38,21 @@ impl ArgminMul, Col> for E { } } -/// ColRef * E -> Col -impl ArgminMul> for ColRef<'_, E> { +/// ColRef * ColRef -> Col (pointwise multiplication) +impl ArgminMul, Col> for ColRef<'_, E> { #[inline] - fn mul(&self, other: &E) -> Col { + fn mul(&self, other: &ColRef<'_, E>) -> Col { let mut result = Col::zeros(self.nrows()); // TODO: why not possible like sub - zip!(&mut result, self).for_each(|unzip!(result, self_)| *result = self_.mul_by_ref(other)); + zip!(&mut result, self, other) + .for_each(|unzip!(result, this, other)| *result = this.mul_by_ref(other)); result } } -/// Col * E -> Col -impl ArgminMul> for Col { +/// Col * Col -> Col (pointwise multiplication) +impl ArgminMul, Col> for Col { #[inline] - fn mul(&self, other: &E) -> Col { - <_ as ArgminMul<_, _>>::mul(&self.as_ref(), other) + fn mul(&self, other: &Col) -> Col { + <_ as ArgminMul<_, _>>::mul(&self.as_ref(), &other.as_ref()) } } diff --git a/crates/argmin-math/src/faer_m_0_21/col/sub.rs b/crates/argmin-math/src/faer_m_0_21/col/sub.rs index 6a736d980..93a846e81 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/sub.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/sub.rs @@ -1,7 +1,6 @@ use crate::ArgminSub; use faer::{unzip, zip, Col, ColMut, ColRef}; use faer_traits::{ComplexField, Conjugate, SubByRef}; -use std::ops::{Sub, SubAssign}; /// ColRef / Scalar -> Col impl ArgminSub> for ColRef<'_, E> { @@ -29,6 +28,16 @@ where zip!(other).map(|unzip!(other)| self.sub_by_ref(other)) } } +/// Scalar / Col -> Col +impl<'a, E> ArgminSub, Col> for E +where + E: ComplexField, +{ + #[inline] + fn sub(&self, other: &Col) -> Col { + <_ as ArgminSub<_, _>>::sub(self, &other.as_ref()) + } +} /// ColRef / ColRef -> Col impl ArgminSub, Col> for ColRef<'_, E> { diff --git a/crates/argmin-math/src/faer_m_0_21/sub.rs b/crates/argmin-math/src/faer_m_0_21/sub.rs index 778433e5b..164ffa3ef 100644 --- a/crates/argmin-math/src/faer_m_0_21/sub.rs +++ b/crates/argmin-math/src/faer_m_0_21/sub.rs @@ -1,7 +1,6 @@ use crate::ArgminSub; use faer::{mat::AsMatRef, unzip, zip, Mat, MatRef}; use faer_traits::{ComplexField, Conjugate, SubByRef}; -use std::ops::{Sub, SubAssign}; /// MatRef / Scalar -> Mat impl ArgminSub> for MatRef<'_, E> From c2485b965494da3a6c86b91e931f969f76669932 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Thu, 15 Jan 2026 11:48:34 +0100 Subject: [PATCH 08/21] remove faer from default features --- crates/argmin-math/Cargo.toml | 2 +- rust-analyzer.toml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 rust-analyzer.toml diff --git a/crates/argmin-math/Cargo.toml b/crates/argmin-math/Cargo.toml index 670f855a0..cef39b733 100644 --- a/crates/argmin-math/Cargo.toml +++ b/crates/argmin-math/Cargo.toml @@ -61,7 +61,7 @@ paste = "1" approx = "0.5.0" [features] -default = ["primitives", "vec", "rand", "faer_v0_23"] +default = ["primitives", "vec", "rand"] latest_all = ["primitives", "vec", "rand", "nalgebra_latest", "ndarray_latest"] # primitives diff --git a/rust-analyzer.toml b/rust-analyzer.toml new file mode 100644 index 000000000..9d8627b05 --- /dev/null +++ b/rust-analyzer.toml @@ -0,0 +1,2 @@ +[rust-analyzer.cargo] +features = "all" From 032ebef7970e9e7e74ccd3835d987abc796e6f67 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Thu, 22 Jan 2026 21:36:45 +0100 Subject: [PATCH 09/21] complete col dot --- crates/argmin-math/src/faer_m_0_21/col/dot.rs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/crates/argmin-math/src/faer_m_0_21/col/dot.rs b/crates/argmin-math/src/faer_m_0_21/col/dot.rs index f92866951..9fb689fe6 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/dot.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/dot.rs @@ -82,3 +82,44 @@ mod scalar_product { } } } + +//@note(clouds) implemented for compatibility with the nalgebra implementations +// see geo's comment in the faer_m_0_21 module (super) +mod multiply_matrix_with_scalar { + use super::*; + use crate::ArgminMul; + use faer_traits::ComplexField; + use std::ops::Mul; + + // ColRef . Scalar -> Col + impl ArgminDot> for ColRef<'_, E> { + #[inline] + fn dot(&self, other: &E) -> Col { + >::mul(self, other) + } + } + + // Col . Scalar -> Col + impl ArgminDot> for Col { + #[inline] + fn dot(&self, other: &E) -> Col { + <_ as ArgminDot>::dot(&self.as_ref(), other) + } + } + + // ColRef . Scalar -> Col + impl<'a, E: ComplexField> ArgminDot, Col> for E { + #[inline] + fn dot(&self, other: &ColRef<'a, E>) -> Col { + , _>>::mul(self, other) + } + } + + // Col . Scalar -> Col + impl ArgminDot, Col> for E { + #[inline] + fn dot(&self, other: &Col) -> Col { + >::dot(self, &other.as_ref()) + } + } +} From 6b7d02093427aeccbedae5a47f044f30b52ad66c Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Thu, 22 Jan 2026 22:09:00 +0100 Subject: [PATCH 10/21] start implementing tests for col dot --- crates/argmin-math/src/faer_m_0_21/sub.rs | 3 ++ crates/argmin-math/src/faer_tests.rs | 3 ++ crates/argmin-math/src/faer_tests/col/dot.rs | 30 +++++++++++++++++++ crates/argmin-math/src/faer_tests/col/mod.rs | 1 + .../argmin-math/src/faer_tests/test_helper.rs | 14 +++++++++ 5 files changed, 51 insertions(+) create mode 100644 crates/argmin-math/src/faer_tests/col/dot.rs create mode 100644 crates/argmin-math/src/faer_tests/col/mod.rs diff --git a/crates/argmin-math/src/faer_m_0_21/sub.rs b/crates/argmin-math/src/faer_m_0_21/sub.rs index 164ffa3ef..593ea1f26 100644 --- a/crates/argmin-math/src/faer_m_0_21/sub.rs +++ b/crates/argmin-math/src/faer_m_0_21/sub.rs @@ -2,6 +2,9 @@ use crate::ArgminSub; use faer::{mat::AsMatRef, unzip, zip, Mat, MatRef}; use faer_traits::{ComplexField, Conjugate, SubByRef}; +#[cfg(feature = "faer_v0_21")] +use faer::{unzip, zip}; + /// MatRef / Scalar -> Mat impl ArgminSub> for MatRef<'_, E> where diff --git a/crates/argmin-math/src/faer_tests.rs b/crates/argmin-math/src/faer_tests.rs index b2b22f0ae..38a2a501d 100644 --- a/crates/argmin-math/src/faer_tests.rs +++ b/crates/argmin-math/src/faer_tests.rs @@ -15,4 +15,7 @@ mod sub; mod transpose; mod zero; +#[cfg(not(feature = "faer_v0_20"))] +mod col; + pub mod test_helper; diff --git a/crates/argmin-math/src/faer_tests/col/dot.rs b/crates/argmin-math/src/faer_tests/col/dot.rs new file mode 100644 index 000000000..64e3de568 --- /dev/null +++ b/crates/argmin-math/src/faer_tests/col/dot.rs @@ -0,0 +1,30 @@ +use crate::faer_tests::test_helper::*; +use crate::ArgminDot; +use approx::assert_relative_eq; +use faer::mat::AsMatRef; +use faer::Mat; +use paste::item; + +macro_rules! make_test { + ($t:ty) => { + item! { + #[test] + fn []() { + let a = col3_new(1 as $t, 2 as $t, 3 as $t); + let b = col3_new(4 as $t, 5 as $t, 6 as $t); + // all owned and reference type combinations + let res1: $t = <_ as ArgminDot<_, _>>::dot(&a, &b); + let res2: $t = <_ as ArgminDot<_, _>>::dot(&a.as_ref(), &b); + let res3: $t = <_ as ArgminDot<_, _>>::dot(&a, &b.as_ref()); + let res4: $t = <_ as ArgminDot<_, _>>::dot(&a.as_ref(), &b.as_ref()); + assert_relative_eq!(res1 as f64, 32 as f64, epsilon = f64::EPSILON); + assert_relative_eq!(res2 as f64, 32 as f64, epsilon = f64::EPSILON); + assert_relative_eq!(res3 as f64, 32 as f64, epsilon = f64::EPSILON); + assert_relative_eq!(res4 as f64, 32 as f64, epsilon = f64::EPSILON); + } + } + }; +} + +make_test!(f32); +make_test!(f64); diff --git a/crates/argmin-math/src/faer_tests/col/mod.rs b/crates/argmin-math/src/faer_tests/col/mod.rs new file mode 100644 index 000000000..e6ebb182a --- /dev/null +++ b/crates/argmin-math/src/faer_tests/col/mod.rs @@ -0,0 +1 @@ +mod dot; diff --git a/crates/argmin-math/src/faer_tests/test_helper.rs b/crates/argmin-math/src/faer_tests/test_helper.rs index 404590ddb..ded52a097 100644 --- a/crates/argmin-math/src/faer_tests/test_helper.rs +++ b/crates/argmin-math/src/faer_tests/test_helper.rs @@ -1,3 +1,4 @@ +use faer::Col; use faer::Mat; cfg_if::cfg_if! { @@ -25,6 +26,11 @@ pub fn column_vector_from_slice(slice: &[E]) -> Mat { Mat::::from_fn(slice.len(), 1, |ir, _ic| slice[ir]) } +/// create an owning column vector from a slice +pub fn col_from_slice(slice: &[E]) -> Col { + Col::::from_fn(slice.len(), |i| slice[i]) +} + /// helper method to translate an nalgebra call Vector3::new(a,b,c) to the /// equivalent faer matrix constructor pub fn vector3_new(a: E, b: E, c: E) -> Mat { @@ -34,6 +40,14 @@ pub fn vector3_new(a: E, b: E, c: E) -> Mat { v } +/// helper method to translate and nalgebra call Vector3::new(a,b,c) to the +/// equivalent faer col constructor +pub fn col3_new(a: E, b: E, c: E) -> Col { + let v = col_from_slice(&[a, b, c]); + assert_eq!(v.nrows(), 3); + v +} + /// helper method to translate an nalgebra call RowVector3::new(a,b,c) to the /// equivalent faer matrix constructor pub fn row_vector3_new(a: E, b: E, c: E) -> Mat { From ca494d2e962ab04d28de118bccb2252c5868d6b5 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 23 Jan 2026 10:31:17 +0100 Subject: [PATCH 11/21] test all dot operations on col --- crates/argmin-math/src/faer_m_0_21/col/dot.rs | 14 ++-- crates/argmin-math/src/faer_m_0_21/dot.rs | 4 +- crates/argmin-math/src/faer_tests/col/dot.rs | 67 ++++++++++++++++++- 3 files changed, 75 insertions(+), 10 deletions(-) diff --git a/crates/argmin-math/src/faer_m_0_21/col/dot.rs b/crates/argmin-math/src/faer_m_0_21/col/dot.rs index 9fb689fe6..29c37f58e 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/dot.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/dot.rs @@ -45,7 +45,7 @@ mod scalar_product { use super::*; use faer_traits::Conjugate; - /// ColRef . ColRef -> Col + /// ColRef . ColRef -> Scalar impl> ArgminDot, E> for ColRef<'_, E> { #[inline] fn dot(&self, other: &ColRef<'_, E>) -> E { @@ -58,7 +58,7 @@ mod scalar_product { } } - /// Col . ColRef -> Col + /// Col . ColRef -> Scalar impl> ArgminDot, E> for Col { #[inline] fn dot(&self, other: &ColRef<'_, E>) -> E { @@ -66,7 +66,7 @@ mod scalar_product { } } - /// ColRef . Col -> Col + /// ColRef . Col -> Scalar impl> ArgminDot, E> for ColRef<'_, E> { #[inline] fn dot(&self, other: &Col) -> E { @@ -74,7 +74,7 @@ mod scalar_product { } } - /// Col . Col -> Col + /// Col . Col -> Scalar impl> ArgminDot, E> for Col { #[inline] fn dot(&self, other: &Col) -> E { @@ -85,7 +85,7 @@ mod scalar_product { //@note(clouds) implemented for compatibility with the nalgebra implementations // see geo's comment in the faer_m_0_21 module (super) -mod multiply_matrix_with_scalar { +mod multiply_col_with_scalar { use super::*; use crate::ArgminMul; use faer_traits::ComplexField; @@ -107,7 +107,7 @@ mod multiply_matrix_with_scalar { } } - // ColRef . Scalar -> Col + // Scalar . ColRef -> Col impl<'a, E: ComplexField> ArgminDot, Col> for E { #[inline] fn dot(&self, other: &ColRef<'a, E>) -> Col { @@ -115,7 +115,7 @@ mod multiply_matrix_with_scalar { } } - // Col . Scalar -> Col + // Scalar . Col -> Col impl ArgminDot, Col> for E { #[inline] fn dot(&self, other: &Col) -> Col { diff --git a/crates/argmin-math/src/faer_m_0_21/dot.rs b/crates/argmin-math/src/faer_m_0_21/dot.rs index 34342c297..ba98b14fe 100644 --- a/crates/argmin-math/src/faer_m_0_21/dot.rs +++ b/crates/argmin-math/src/faer_m_0_21/dot.rs @@ -136,7 +136,7 @@ mod multiply_matrix_with_scalar { } } - // MatRef . Scalar -> Mat + // Scalar . MatRef -> Mat impl<'a, E: ComplexField> ArgminDot, Mat> for E { #[inline] fn dot(&self, other: &MatRef<'a, E>) -> Mat { @@ -144,7 +144,7 @@ mod multiply_matrix_with_scalar { } } - // Mat . Scalar -> Mat + // Scalar . Mat -> Mat impl ArgminDot, Mat> for E { #[inline] fn dot(&self, other: &Mat) -> Mat { diff --git a/crates/argmin-math/src/faer_tests/col/dot.rs b/crates/argmin-math/src/faer_tests/col/dot.rs index 64e3de568..3878ae460 100644 --- a/crates/argmin-math/src/faer_tests/col/dot.rs +++ b/crates/argmin-math/src/faer_tests/col/dot.rs @@ -2,7 +2,7 @@ use crate::faer_tests::test_helper::*; use crate::ArgminDot; use approx::assert_relative_eq; use faer::mat::AsMatRef; -use faer::Mat; +use faer::Col; use paste::item; macro_rules! make_test { @@ -23,6 +23,71 @@ macro_rules! make_test { assert_relative_eq!(res4 as f64, 32 as f64, epsilon = f64::EPSILON); } } + + item! { + #[test] + fn []() { + let a = col3_new(1 as $t, 2 as $t, 3 as $t); + let b = 2 as $t; + let product1: Col<$t> = + <_ as ArgminDot<$t, _>>::dot(&a, &b); + let product2: Col<$t> = + <_ as ArgminDot<$t, _>>::dot(&a.as_ref(), &b); + let res = col3_new(2 as $t, 4 as $t, 6 as $t); + assert_eq!(product1,product2); + assert_eq!(product1.nrows(),3); + assert_eq!(product1.ncols(),1); + for i in 0..3 { + assert_relative_eq!(res[i] as f64, product1[i] as f64, epsilon = f64::EPSILON); + } + } + } + + item! { + #[test] + fn []() { + let a = col3_new(1 as $t, 2 as $t, 3 as $t); + let b = 2 as $t; + let product1: Col<$t> = + <$t as ArgminDot<_, _>>::dot(&b, &a); + let product2: Col<$t> = + <$t as ArgminDot<_, _>>::dot(&b, &a.as_ref()); + assert_eq!(product1,product2); + assert_eq!(product1.nrows(),3); + assert_eq!(product1.ncols(),1); + let res = col3_new(2 as $t, 4 as $t, 6 as $t); + for i in 0..3 { + assert_relative_eq!(res[i] as f64, product1[i] as f64, epsilon = f64::EPSILON); + } + } + } + + item! { + #[test] // corresponds to test_mat_vec_2_ in super + fn []() { + let a = matrix3_new( + 1 as $t, 2 as $t, 3 as $t, + 4 as $t, 5 as $t, 6 as $t, + 7 as $t, 8 as $t, 9 as $t + ); + let b = col3_new(1 as $t, 2 as $t, 3 as $t); + let res = col3_new(14 as $t, 32 as $t, 50 as $t); + let product1: Col<$t> = + <_ as ArgminDot<_, _>>::dot(&a, &b); + let product2: Col<$t> = + <_ as ArgminDot<_, _>>::dot(&a.as_mat_ref(), &b); + let product3: Col<$t> = + <_ as ArgminDot<_, _>>::dot(&a, &b.as_ref()); + let product4: Col<$t> = + <_ as ArgminDot<_, _>>::dot(&a.as_mat_ref(), &b.as_ref()); + for i in 0..3 { + assert_relative_eq!(res[i] as f64, product1[i] as f64, epsilon = f64::EPSILON); + assert_relative_eq!(res[i] as f64, product2[i] as f64, epsilon = f64::EPSILON); + assert_relative_eq!(res[i] as f64, product3[i] as f64, epsilon = f64::EPSILON); + assert_relative_eq!(res[i] as f64, product4[i] as f64, epsilon = f64::EPSILON); + } + } + } }; } From 350022f671df4c743f8b1288c47a43e767fca5a8 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 23 Jan 2026 10:39:03 +0100 Subject: [PATCH 12/21] add tests for l2 norm on col --- .../argmin-math/src/faer_tests/col/l2norm.rs | 38 +++++++++++++++++++ crates/argmin-math/src/faer_tests/col/mod.rs | 1 + .../argmin-math/src/faer_tests/test_helper.rs | 9 +++++ 3 files changed, 48 insertions(+) create mode 100644 crates/argmin-math/src/faer_tests/col/l2norm.rs diff --git a/crates/argmin-math/src/faer_tests/col/l2norm.rs b/crates/argmin-math/src/faer_tests/col/l2norm.rs new file mode 100644 index 000000000..3d847c114 --- /dev/null +++ b/crates/argmin-math/src/faer_tests/col/l2norm.rs @@ -0,0 +1,38 @@ +use crate::faer_tests::test_helper::*; +use crate::ArgminL2Norm; +use approx::assert_relative_eq; +use paste::item; + +macro_rules! make_test { + ($t:ty) => { + item! { + #[test] + fn []() { + let a = col2_new(4 as $t, 3 as $t); + let res = <_ as ArgminL2Norm<$t>>::l2_norm(&a); + let target = 5 as $t; + assert_relative_eq!(target as $t, res as $t, epsilon = $t::EPSILON); + } + } + }; +} + +macro_rules! make_test_signed { + ($t:ty) => { + item! { + #[test] + fn []() { + let a = col2_new(-4 as $t, -3 as $t); + let res = <_ as ArgminL2Norm<$t>>::l2_norm(&a); + let target = 5 as $t; + assert_relative_eq!(target as $t, res as $t, epsilon = $t::EPSILON); + } + } + }; +} + +make_test!(f32); +make_test!(f64); + +make_test_signed!(f32); +make_test_signed!(f64); diff --git a/crates/argmin-math/src/faer_tests/col/mod.rs b/crates/argmin-math/src/faer_tests/col/mod.rs index e6ebb182a..c7dbe9d53 100644 --- a/crates/argmin-math/src/faer_tests/col/mod.rs +++ b/crates/argmin-math/src/faer_tests/col/mod.rs @@ -1 +1,2 @@ mod dot; +mod l2norm; diff --git a/crates/argmin-math/src/faer_tests/test_helper.rs b/crates/argmin-math/src/faer_tests/test_helper.rs index ded52a097..d84dc1880 100644 --- a/crates/argmin-math/src/faer_tests/test_helper.rs +++ b/crates/argmin-math/src/faer_tests/test_helper.rs @@ -66,6 +66,15 @@ pub fn vector2_new(a: E, b: E) -> Mat { v } +/// helper method to translate an nalgebra call Vector2::new(a,b) to the +/// equivalent faer col constructor +pub fn col2_new(a: E, b: E) -> Col { + let v = col_from_slice(&[a, b]); + assert_eq!(v.nrows(), 2); + assert_eq!(v.ncols(), 1); + v +} + /// helper method to translate an nalgebra call Matrix2x3::new(a,b,c, d,e,f) to the /// equivalent faer matrix constructor pub fn matrix2x3_new(a: E, b: E, c: E, d: E, e: E, f: E) -> Mat { From 78e4f24d85c662abeff29a26b330a5b04d9e1706 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 23 Jan 2026 10:52:48 +0100 Subject: [PATCH 13/21] add tests for mul on col --- crates/argmin-math/src/faer_m_0_21/col/mul.rs | 25 +++++-- crates/argmin-math/src/faer_m_0_21/mul.rs | 2 +- crates/argmin-math/src/faer_tests/col/mod.rs | 1 + crates/argmin-math/src/faer_tests/col/mul.rs | 66 +++++++++++++++++++ 4 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 crates/argmin-math/src/faer_tests/col/mul.rs diff --git a/crates/argmin-math/src/faer_m_0_21/col/mul.rs b/crates/argmin-math/src/faer_m_0_21/col/mul.rs index 599372ba7..03862a762 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/mul.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/mul.rs @@ -6,9 +6,7 @@ use faer_traits::{ComplexField, MulByRef}; impl ArgminMul> for ColRef<'_, E> { #[inline] fn mul(&self, other: &E) -> Col { - let mut result = Col::zeros(self.nrows()); // TODO: why not possible like sub - zip!(&mut result, self).for_each(|unzip!(result, self_)| *result = self_.mul_by_ref(other)); - result + zip!(self).map(|unzip!(this)| this.mul_by_ref(other)) } } @@ -16,9 +14,8 @@ impl ArgminMul> for ColRef<'_, E> { impl ArgminMul, Col> for E { #[inline] fn mul(&self, other: &ColRef<'_, E>) -> Col { - let mut result = Col::zeros(other.nrows()); // TODO: why not possible like sub - zip!(&mut result, other).for_each(|unzip!(result, other)| *result = self.mul_by_ref(other)); - result + // commutative with ColRef * Scalar so we can fall back on that case + <_ as ArgminMul<_, _>>::mul(other, self) } } @@ -49,6 +46,22 @@ impl ArgminMul, Col> for ColRef<'_, E> { } } +/// ColRef * Col -> Col (pointwise multiplication) +impl ArgminMul, Col> for ColRef<'_, E> { + #[inline] + fn mul(&self, other: &Col) -> Col { + <_ as ArgminMul<_, _>>::mul(self, &other.as_ref()) + } +} + +/// Col * ColRef -> Col (pointwise multiplication) +impl ArgminMul, Col> for Col { + #[inline] + fn mul(&self, other: &ColRef) -> Col { + <_ as ArgminMul<_, _>>::mul(&self.as_ref(), other) + } +} + /// Col * Col -> Col (pointwise multiplication) impl ArgminMul, Col> for Col { #[inline] diff --git a/crates/argmin-math/src/faer_m_0_21/mul.rs b/crates/argmin-math/src/faer_m_0_21/mul.rs index 0d0ba1f18..b85ed056b 100644 --- a/crates/argmin-math/src/faer_m_0_21/mul.rs +++ b/crates/argmin-math/src/faer_m_0_21/mul.rs @@ -25,7 +25,7 @@ where { #[inline] fn mul(&self, other: &MatRef<'a, E>) -> Mat { - // commutative with MatRef + Scalar so we can fall back on that case + // commutative with MatRef * Scalar so we can fall back on that case <_ as ArgminMul<_, _>>::mul(other, self) } } diff --git a/crates/argmin-math/src/faer_tests/col/mod.rs b/crates/argmin-math/src/faer_tests/col/mod.rs index c7dbe9d53..194286389 100644 --- a/crates/argmin-math/src/faer_tests/col/mod.rs +++ b/crates/argmin-math/src/faer_tests/col/mod.rs @@ -1,2 +1,3 @@ mod dot; mod l2norm; +mod mul; diff --git a/crates/argmin-math/src/faer_tests/col/mul.rs b/crates/argmin-math/src/faer_tests/col/mul.rs new file mode 100644 index 000000000..c3a6e7922 --- /dev/null +++ b/crates/argmin-math/src/faer_tests/col/mul.rs @@ -0,0 +1,66 @@ +use crate::faer_tests::test_helper::*; +use crate::ArgminMul; +use approx::assert_relative_eq; +use paste::item; + +macro_rules! make_test { + ($t:ty) => { + item! { + #[test] + fn []() { + let a = col3_new(1 as $t, 4 as $t, 8 as $t); + let b = 2 as $t; + let target = col3_new(2 as $t, 8 as $t, 16 as $t); + let res = <_ as ArgminMul<_, _>>::mul(&a, &b); + let res2 = <_ as ArgminMul<_, _>>::mul(&a.as_ref(), &b); + assert_eq!(res,res2); + assert_eq!(res.nrows(),3); + assert_eq!(res.ncols(),1); + for i in 0..3 { + assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON); + } + } + } + + item! { + #[test] + fn []() { + let a = col3_new(1 as $t, 4 as $t, 8 as $t); + let b = 2 as $t; + let target = col3_new(2 as $t, 8 as $t, 16 as $t); + let res = <_ as ArgminMul<_,_>>::mul(&b, &a); + let res2 = <_ as ArgminMul<_, _>>::mul(&b, &a.as_ref()); + assert_eq!(res,res2); + assert_eq!(res.nrows(),3); + assert_eq!(res.ncols(),1); + for i in 0..3 { + assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON); + } + } + } + + item! { + #[test] + fn []() { + let a = col3_new(1 as $t, 4 as $t, 8 as $t); + let b = col3_new(2 as $t, 3 as $t, 4 as $t); + let target = col3_new(2 as $t, 12 as $t, 32 as $t); + let res = <_ as ArgminMul<_,_>>::mul(&a, &b); + let res2 = <_ as ArgminMul<_,_>>::mul(&a.as_ref(), &b); + let res3 = <_ as ArgminMul<_,_>>::mul(&a, &b.as_ref()); + let res4 = <_ as ArgminMul<_,_>>::mul(&a.as_ref(), &b.as_ref()); + assert_eq!(res.nrows(),3); + assert_eq!(res.ncols(),1); + assert_eq!(res,res2); + assert_eq!(res,res3); + assert_eq!(res,res4); + for i in 0..3 { + assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON); + } + } + } + }; +} + +make_test!(f32); +make_test!(f64); From 33b3ba4d728533cb28734244f13c0a8fb5b7ebaf Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 23 Jan 2026 11:00:53 +0100 Subject: [PATCH 14/21] add tests for sub on col --- crates/argmin-math/src/faer_tests/col/mod.rs | 1 + crates/argmin-math/src/faer_tests/col/sub.rs | 67 +++++++++++++++++++ .../argmin-math/src/faer_tests/test_helper.rs | 6 ++ 3 files changed, 74 insertions(+) create mode 100644 crates/argmin-math/src/faer_tests/col/sub.rs diff --git a/crates/argmin-math/src/faer_tests/col/mod.rs b/crates/argmin-math/src/faer_tests/col/mod.rs index 194286389..26952bb50 100644 --- a/crates/argmin-math/src/faer_tests/col/mod.rs +++ b/crates/argmin-math/src/faer_tests/col/mod.rs @@ -1,3 +1,4 @@ mod dot; mod l2norm; mod mul; +mod sub; diff --git a/crates/argmin-math/src/faer_tests/col/sub.rs b/crates/argmin-math/src/faer_tests/col/sub.rs new file mode 100644 index 000000000..97e5a7d2e --- /dev/null +++ b/crates/argmin-math/src/faer_tests/col/sub.rs @@ -0,0 +1,67 @@ +use crate::faer_tests::test_helper::*; +use crate::ArgminSub; +use approx::assert_relative_eq; +use faer::Col; +use paste::item; + +macro_rules! make_test { + ($t:ty) => { + item! { + #[test] + fn []() { + let a: Col<$t> = col_from_vec(vec![36 as $t, 39 as $t, 43 as $t]); + let b: $t = 1 as $t; + let target: Col<$t> = col_from_vec(vec![35 as $t, 38 as $t, 42 as $t]); + // make sure we get the same answer regardless whether we + // use owned matrices or matrix references. + let res = <_ as ArgminSub<_,_>>::sub(&a, &b); + let res2 = <_ as ArgminSub<_,_>>::sub(&a.as_ref(), &b); + assert_eq!(res.nrows(),3); + assert_eq!(res,res2); + for i in 0..3 { + assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON); + } + } + } + + item! { + #[test] + fn []() { + let a = 34 as $t; + let b = col_from_vec(vec![1 as $t, 4 as $t, 8 as $t]); + let target = col_from_vec(vec![33 as $t, 30 as $t, 26 as $t]); + let res = <$t as ArgminSub<_,_>>::sub(&a, &b); + let res2 = <$t as ArgminSub<_,_>>::sub(&a, &b.as_ref()); + assert_eq!(res.nrows(),3); + assert_eq!(res,res2); + for i in 0..3 { + assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON); + } + } + } + + item! { + #[test] + fn []() { + let a: Col<$t> = col_from_vec(vec![41 as $t, 38 as $t, 34 as $t]); + let b: Col<$t> = col_from_vec(vec![1 as $t, 4 as $t, 8 as $t]); + let target: Col<$t> = col_from_vec(vec![40 as $t, 34 as $t, 26 as $t]); + // all combinations of references and owned matrices + let res = <_ as ArgminSub<_,_>>::sub(&a, &b); + let res2 = <_ as ArgminSub<_,_>>::sub(&a.as_ref(), &b); + let res3 = <_ as ArgminSub<_,_>>::sub(&a, &b.as_ref()); + let res4 = <_ as ArgminSub<_,_>>::sub(&a.as_ref(), &b.as_ref()); + assert_eq!(res.nrows(),3); + assert_eq!(res,res2); + assert_eq!(res,res3); + assert_eq!(res,res4); + for i in 0..3 { + assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON); + } + } + } + }; +} + +make_test!(f32); +make_test!(f64); diff --git a/crates/argmin-math/src/faer_tests/test_helper.rs b/crates/argmin-math/src/faer_tests/test_helper.rs index d84dc1880..66e3c36e5 100644 --- a/crates/argmin-math/src/faer_tests/test_helper.rs +++ b/crates/argmin-math/src/faer_tests/test_helper.rs @@ -21,6 +21,12 @@ pub fn column_vector_from_vec(vec: Vec) -> Mat { column_vector_from_slice(vec.as_slice()) } +/// create a column vector from a Vec instance +/// equivalent to the nalgebra call DVector::from_vec +pub fn col_from_vec(vec: Vec) -> Col { + col_from_slice(vec.as_slice()) +} + /// create an owning column vector from a slice pub fn column_vector_from_slice(slice: &[E]) -> Mat { Mat::::from_fn(slice.len(), 1, |ir, _ic| slice[ir]) From f2dc70872632a5dec9fd87244658972684dc25e0 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 23 Jan 2026 11:02:24 +0100 Subject: [PATCH 15/21] remove unused lifetime --- crates/argmin-math/src/faer_m_0_21/col/sub.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/argmin-math/src/faer_m_0_21/col/sub.rs b/crates/argmin-math/src/faer_m_0_21/col/sub.rs index 93a846e81..bfc13db5d 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/sub.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/sub.rs @@ -29,7 +29,7 @@ where } } /// Scalar / Col -> Col -impl<'a, E> ArgminSub, Col> for E +impl ArgminSub, Col> for E where E: ComplexField, { From ead7678b327b33a6726221b658b9b1ef9226b22e Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 23 Jan 2026 20:10:07 +0100 Subject: [PATCH 16/21] implement add for col --- crates/argmin-math/src/faer_m_0_21/col/add.rs | 90 +++++++++++++++++++ crates/argmin-math/src/faer_m_0_21/col/mod.rs | 1 + crates/argmin-math/src/faer_tests/col/add.rs | 86 ++++++++++++++++++ crates/argmin-math/src/faer_tests/col/mod.rs | 1 + rust-analyzer.toml | 2 - 5 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 crates/argmin-math/src/faer_m_0_21/col/add.rs create mode 100644 crates/argmin-math/src/faer_tests/col/add.rs delete mode 100644 rust-analyzer.toml diff --git a/crates/argmin-math/src/faer_m_0_21/col/add.rs b/crates/argmin-math/src/faer_m_0_21/col/add.rs new file mode 100644 index 000000000..2b13db40a --- /dev/null +++ b/crates/argmin-math/src/faer_m_0_21/col/add.rs @@ -0,0 +1,90 @@ +use crate::ArgminAdd; +use faer::{ + mat::{AsMatMut, AsMatRef}, + unzip, zip, Col, ColRef, Mat, MatMut, MatRef, +}; +use faer_traits::ComplexField; + +/// ColRef + Scalar -> Col +impl ArgminAdd> for ColRef<'_, E> +where + E: ComplexField, +{ + #[inline] + fn add(&self, other: &E) -> Col { + zip!(self).map(|unzip!(this)| this.add_by_ref(other)) + } +} + +/// Scalar + ColRef-> Col +impl<'a, E> ArgminAdd, Col> for E +where + E: ComplexField, +{ + #[inline] + fn add(&self, other: &ColRef<'a, E>) -> Col { + // commutative with MatRef + Scalar so we can fall back on that case + <_ as ArgminAdd<_, _>>::add(other, self) + } +} + +/// Col + Scalar -> Col +impl ArgminAdd> for Col +where + E: ComplexField, +{ + #[inline] + fn add(&self, other: &E) -> Col { + //@note(geo-ant) because we are taking self by reference we + // cannot mutate the matrix in place, so we can just as well + // reuse the reference code + <_ as ArgminAdd<_, _>>::add(&self.as_ref(), other) + } +} + +/// Scalar + Col -> Col +impl ArgminAdd, Col> for E +where + E: ComplexField, +{ + #[inline] + fn add(&self, other: &Col) -> Col { + // commutative with Col + Scalar so we can fall back on that case + <_ as ArgminAdd<_, _>>::add(other, self) + } +} + +/// ColRef + ColRef -> Col +impl<'a, E> ArgminAdd, Col> for ColRef<'_, E> +where + E: ComplexField, +{ + #[inline] + fn add(&self, other: &ColRef<'a, E>) -> Col { + self + other + } +} + +/// ColRef + Col -> Col +impl ArgminAdd, Col> for ColRef<'_, E> { + #[inline] + fn add(&self, other: &Col) -> Col { + self + other + } +} + +/// Col + ColRef -> Col +impl ArgminAdd, Col> for Col { + #[inline] + fn add(&self, other: &ColRef<'_, E>) -> Col { + self + other + } +} + +/// Col + Col -> Col +impl ArgminAdd, Col> for Col { + #[inline] + fn add(&self, other: &Col) -> Col { + self + other + } +} diff --git a/crates/argmin-math/src/faer_m_0_21/col/mod.rs b/crates/argmin-math/src/faer_m_0_21/col/mod.rs index d25070d28..e3d275a46 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/mod.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/mod.rs @@ -1,3 +1,4 @@ +mod add; mod dot; mod l2_norm; mod mul; diff --git a/crates/argmin-math/src/faer_tests/col/add.rs b/crates/argmin-math/src/faer_tests/col/add.rs new file mode 100644 index 000000000..a97cd0a3c --- /dev/null +++ b/crates/argmin-math/src/faer_tests/col/add.rs @@ -0,0 +1,86 @@ +use crate::faer_tests::test_helper::*; +use crate::ArgminAdd; +use approx::assert_relative_eq; +use paste::item; + +macro_rules! make_test { + ($t:ty) => { + item! { + #[test] + fn []() { + let a = col3_new(1 as $t, 4 as $t, 8 as $t); + let b = 34 as $t; + let target = col3_new(35 as $t, 38 as $t, 42 as $t); + let res1 = <_ as ArgminAdd<$t, _>>::add(&a, &b); + let res2 = <_ as ArgminAdd<$t, _>>::add(&a.as_ref(), &b); + assert_eq!(res1, res2); + assert_eq!(res1.nrows(), 3); + for i in 0..3 { + assert_relative_eq!(target[i] as f64, res1[i] as f64, epsilon = f64::EPSILON); + } + } + } + + item! { + #[test] + fn []() { + let a = col3_new(1 as $t, 4 as $t, 8 as $t); + let b = 34 as $t; + let target = col3_new(35 as $t, 38 as $t, 42 as $t); + let res1 = <_ as ArgminAdd<_, _>>::add(&b, &a); + let res2 = <_ as ArgminAdd<_, _>>::add(&b, &a.as_ref()); + assert_eq!(res1, res2); + assert_eq!(res1.nrows(), 3); + for i in 0..3 { + assert_relative_eq!(target[i] as f64, res1[i] as f64, epsilon = f64::EPSILON); + } + } + } + + item! { + #[test] + fn []() { + let a = col3_new(1 as $t, 4 as $t, 8 as $t); + let b = col3_new(41 as $t, 38 as $t, 34 as $t); + let target = col3_new(42 as $t, 42 as $t, 42 as $t); + let res = <_ as ArgminAdd<_, _>>::add(&a, &b); + for i in 0..3 { + assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON); + } + } + } + + item! { + #[test] + #[should_panic] + fn []() { + let a = col_from_vec(vec![1 as $t, 4 as $t]); + let b = col_from_vec(vec![41 as $t, 38 as $t, 34 as $t]); + <_ as ArgminAdd<_,_>>::add(&a, &b); + } + } + + item! { + #[test] + #[should_panic] + fn []() { + let a = col_from_vec(vec![]); + let b = col_from_vec(vec![41 as $t, 38 as $t, 34 as $t]); + <_ as ArgminAdd<_, _>>::add(&a, &b); + } + } + + item! { + #[test] + #[should_panic] + fn []() { + let a = col_from_vec(vec![41 as $t, 38 as $t, 34 as $t]); + let b = col_from_vec(vec![]); + <_ as ArgminAdd<_, _>>::add(&a, &b); + } + } + }; +} + +make_test!(f32); +make_test!(f64); diff --git a/crates/argmin-math/src/faer_tests/col/mod.rs b/crates/argmin-math/src/faer_tests/col/mod.rs index 26952bb50..ac1834f4d 100644 --- a/crates/argmin-math/src/faer_tests/col/mod.rs +++ b/crates/argmin-math/src/faer_tests/col/mod.rs @@ -1,3 +1,4 @@ +mod add; mod dot; mod l2norm; mod mul; diff --git a/rust-analyzer.toml b/rust-analyzer.toml deleted file mode 100644 index 9d8627b05..000000000 --- a/rust-analyzer.toml +++ /dev/null @@ -1,2 +0,0 @@ -[rust-analyzer.cargo] -features = "all" From 92e0c4c75ce0842e5e414dc729bc308365813620 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 23 Jan 2026 20:11:13 +0100 Subject: [PATCH 17/21] use github link as dependency --- crates/argmin-math/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/argmin-math/Cargo.toml b/crates/argmin-math/Cargo.toml index cef39b733..058daa22d 100644 --- a/crates/argmin-math/Cargo.toml +++ b/crates/argmin-math/Cargo.toml @@ -61,7 +61,7 @@ paste = "1" approx = "0.5.0" [features] -default = ["primitives", "vec", "rand"] +default = ["primitives", "vec", "rand", "faer_all", "faer_latest"] latest_all = ["primitives", "vec", "rand", "nalgebra_latest", "ndarray_latest"] # primitives From d9ec87d5868269baf7262d5dc3e81902d420ea4f Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 23 Jan 2026 20:27:31 +0100 Subject: [PATCH 18/21] remove default features faer --- crates/argmin-math/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/argmin-math/Cargo.toml b/crates/argmin-math/Cargo.toml index 058daa22d..cef39b733 100644 --- a/crates/argmin-math/Cargo.toml +++ b/crates/argmin-math/Cargo.toml @@ -61,7 +61,7 @@ paste = "1" approx = "0.5.0" [features] -default = ["primitives", "vec", "rand", "faer_all", "faer_latest"] +default = ["primitives", "vec", "rand"] latest_all = ["primitives", "vec", "rand", "nalgebra_latest", "ndarray_latest"] # primitives From 9e76acce76bc04b92c65a2024de6b1a4df36f83d Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 23 Jan 2026 20:54:03 +0100 Subject: [PATCH 19/21] disable column operations for feature faer_v0_20 --- crates/argmin-math/src/faer_m_0_21/col/mod.rs | 6 ++++++ crates/argmin-math/src/faer_m_0_21/mod.rs | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/argmin-math/src/faer_m_0_21/col/mod.rs b/crates/argmin-math/src/faer_m_0_21/col/mod.rs index e3d275a46..6f2fd2228 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/mod.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/mod.rs @@ -3,3 +3,9 @@ mod dot; mod l2_norm; mod mul; mod sub; + +pub use add::*; +pub use dot::*; +pub use l2_norm::*; +pub use mul::*; +pub use sub::*; diff --git a/crates/argmin-math/src/faer_m_0_21/mod.rs b/crates/argmin-math/src/faer_m_0_21/mod.rs index 857d75288..b0ccb093b 100644 --- a/crates/argmin-math/src/faer_m_0_21/mod.rs +++ b/crates/argmin-math/src/faer_m_0_21/mod.rs @@ -8,7 +8,6 @@ #![allow(unused_imports)] mod add; -mod col; mod conj; mod div; mod dot; @@ -51,3 +50,9 @@ pub use signum::*; pub use sub::*; pub use transpose::*; pub use zero::*; + +#[cfg(not(feature = "faer_v0_20"))] +mod col; + +#[cfg(not(feature = "faer_v0_20"))] +pub use col::*; From 67d3e1efbc3c335bad82bad88aa75e1c3c7e347b Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Tue, 24 Feb 2026 20:55:40 +0100 Subject: [PATCH 20/21] fix tests --- crates/argmin-math/src/faer_m_0_21/col/add.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/argmin-math/src/faer_m_0_21/col/add.rs b/crates/argmin-math/src/faer_m_0_21/col/add.rs index 2b13db40a..d01a524a6 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/add.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/add.rs @@ -3,7 +3,7 @@ use faer::{ mat::{AsMatMut, AsMatRef}, unzip, zip, Col, ColRef, Mat, MatMut, MatRef, }; -use faer_traits::ComplexField; +use faer_traits::{AddByRef, ComplexField}; /// ColRef + Scalar -> Col impl ArgminAdd> for ColRef<'_, E> From 932fd347f6c6dd6e424a01fb7a40eb03b7311c3e Mon Sep 17 00:00:00 2001 From: Clouds Date: Thu, 13 Aug 2026 15:51:47 +0200 Subject: [PATCH 21/21] implement outer product for cols --- crates/argmin-math/src/faer_m_0_21/col/dot.rs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/crates/argmin-math/src/faer_m_0_21/col/dot.rs b/crates/argmin-math/src/faer_m_0_21/col/dot.rs index 29c37f58e..654f8b9a8 100644 --- a/crates/argmin-math/src/faer_m_0_21/col/dot.rs +++ b/crates/argmin-math/src/faer_m_0_21/col/dot.rs @@ -83,6 +83,42 @@ mod scalar_product { } } +mod outer_col_product { + use super::*; + + /// ColRef . ColRef -> Mat + impl ArgminDot, Mat> for ColRef<'_, E> { + #[inline] + fn dot(&self, other: &ColRef<'_, E>) -> Mat { + Mat::from_fn(self.nrows(), other.nrows(), |i, j| &self[i] * &other[j]) + } + } + + /// Col . ColRef -> Mat + impl ArgminDot, Mat> for Col { + #[inline] + fn dot(&self, other: &ColRef<'_, E>) -> Mat { + <_ as ArgminDot<_, _>>::dot(&self.as_ref(), other) + } + } + + /// ColRef . Col -> Mat + impl ArgminDot, Mat> for ColRef<'_, E> { + #[inline] + fn dot(&self, other: &Col) -> Mat { + <_ as ArgminDot<_, _>>::dot(self, &other.as_ref()) + } + } + + /// Col . Col -> Mat + impl ArgminDot, Mat> for Col { + #[inline] + fn dot(&self, other: &Col) -> Mat { + <_ as ArgminDot<_, _>>::dot(&self.as_ref(), &other.as_ref()) + } + } +} + //@note(clouds) implemented for compatibility with the nalgebra implementations // see geo's comment in the faer_m_0_21 module (super) mod multiply_col_with_scalar {