diff --git a/Cargo.toml b/Cargo.toml index 904c88b..d3a53cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,8 +25,8 @@ default = [] minpack-compat = [] [dependencies] -nalgebra = { version = "0.32.1", default-features = false } -num-traits = { version = "0.2.14", default-features = false, features = [ +nalgebra = { version = "0.33", default-features = false } +num-traits = { version = "0.2", default-features = false, features = [ "libm", ] } cfg-if = "1.0.0" @@ -34,7 +34,7 @@ cfg-if = "1.0.0" [dev-dependencies] arrsac = "0.10.0" rand = { version = "0.8.4", default-features = false } -nalgebra = "0.32.1" +nalgebra = "0.33" pcg_rand = "0.13.0" sample-consensus = "1.0.2" approx = "0.5.1" diff --git a/src/lib.rs b/src/lib.rs index cb983fc..2be02ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -107,6 +107,7 @@ //! //! You should try using [`differentiate_numerically`](fn.differentiate_numerically.html) //! in a unit test to verify that your Jacobian implementation matches the residuals. +#![allow(unexpected_cfgs)] #![no_std] #![cfg_attr(feature = "RUSTC_IS_NIGHTLY", core_intrinsics)] diff --git a/src/lm.rs b/src/lm.rs index c770e1a..043016b 100644 --- a/src/lm.rs +++ b/src/lm.rs @@ -257,8 +257,7 @@ impl LevenbergMarquardt { N: Dim, M: DimMin + DimMax, O: LeastSquaresProblem, - DefaultAllocator: - Allocator + Reallocator, N> + Allocator, + DefaultAllocator: Allocator + Reallocator, N>, { let (mut lm, mut residuals) = match LM::new(self, target) { Err(report) => return report, @@ -309,7 +308,7 @@ where N: Dim, M: DimMin + DimMax, O: LeastSquaresProblem, - DefaultAllocator: Allocator + Allocator, N>, + DefaultAllocator: Allocator + Allocator, N>, { config: &'a LevenbergMarquardt, /// Current parameters `$\vec{x}$` @@ -342,7 +341,7 @@ where N: Dim, M: DimMin + DimMax, O: LeastSquaresProblem, - DefaultAllocator: Allocator + Allocator, N>, + DefaultAllocator: Allocator + Allocator, N>, { #[allow(clippy::type_complexity)] fn new( @@ -455,7 +454,7 @@ where lls: &mut LinearLeastSquaresDiagonalProblem, ) -> Result<(), TerminationReason> where - DefaultAllocator: Allocator, + DefaultAllocator: Allocator, { // Compute norm of scaled gradient and detect degeneracy self.gnorm = match lls.max_a_t_b_scaled(self.residuals_norm) { @@ -510,7 +509,7 @@ where param: LMParameter, ) -> Result>, TerminationReason> where - DefaultAllocator: Allocator, + DefaultAllocator: Allocator, { const P1: f64 = 0.1; const P0001: f64 = 1.0e-4; diff --git a/src/lm/test_examples.rs b/src/lm/test_examples.rs index 6f2ced7..7c5d962 100644 --- a/src/lm/test_examples.rs +++ b/src/lm/test_examples.rs @@ -512,14 +512,14 @@ impl LeastSquaresProblem for Meyer { #[derive(Clone)] struct Watson where - DefaultAllocator: Allocator, + DefaultAllocator: Allocator

, { params: OVector, } impl Watson

where - DefaultAllocator: Allocator, + DefaultAllocator: Allocator

, { fn new(params: OVector, _n: usize) -> Self { Self { params } @@ -528,7 +528,7 @@ where impl LeastSquaresProblem for Watson

where - DefaultAllocator: Allocator + Allocator, + DefaultAllocator: Allocator

+ Allocator, { type ParameterStorage = Owned; type ResidualStorage = Owned; diff --git a/src/lm/test_helpers.rs b/src/lm/test_helpers.rs index d0a3727..b483438 100644 --- a/src/lm/test_helpers.rs +++ b/src/lm/test_helpers.rs @@ -15,7 +15,7 @@ pub enum MockCall { #[derive(Clone)] pub struct MockProblem where - DefaultAllocator: Allocator + Allocator + Allocator, + DefaultAllocator: Allocator + Allocator + Allocator, { call_history: RefCell>, params: Vec>, @@ -27,7 +27,7 @@ where impl MockProblem where - DefaultAllocator: Allocator + Allocator + Allocator, + DefaultAllocator: Allocator + Allocator + Allocator, { pub fn new(initial: OVector, residuals: Vec>>) -> Self { Self { @@ -47,7 +47,7 @@ where impl LeastSquaresProblem for MockProblem where - DefaultAllocator: Allocator + Allocator + Allocator, + DefaultAllocator: Allocator + Allocator + Allocator, { type ResidualStorage = Owned; type ParameterStorage = Owned; diff --git a/src/lm/test_init_step.rs b/src/lm/test_init_step.rs index 43783db..b64f3c6 100644 --- a/src/lm/test_init_step.rs +++ b/src/lm/test_init_step.rs @@ -1,13 +1,9 @@ +use super::test_helpers::{MockCall, MockProblem}; +use super::{LevenbergMarquardt, TerminationReason, LM}; use alloc::vec; use approx::assert_relative_eq; -#[cfg(not(feature = "minpack-compat"))] -use core::f64::{INFINITY, MIN_POSITIVE, NAN}; - use nalgebra::{Dim, Dyn, OMatrix, OVector, Vector2, Vector3, U0, U2, U3}; -use super::test_helpers::{MockCall, MockProblem}; -use super::{LevenbergMarquardt, TerminationReason, LM}; - #[test] #[cfg(not(feature = "minpack-compat"))] fn nan_or_inf_none_residual() { @@ -20,8 +16,10 @@ fn nan_or_inf_none_residual() { assert!(err.objective_function.is_nan()); // residuals return inf - let problem = - MockProblem::::new(Vector2::zeros(), vec![Some(Vector3::new(1., 1., INFINITY))]); + let problem = MockProblem::::new( + Vector2::zeros(), + vec![Some(Vector3::new(1., 1., f64::INFINITY))], + ); let (mut problem, err) = LM::new(&LevenbergMarquardt::new(), problem).err().unwrap(); assert_eq!( err.termination, @@ -33,7 +31,7 @@ fn nan_or_inf_none_residual() { // residuals return nan let problem = - MockProblem::::new(Vector2::zeros(), vec![Some(Vector3::new(1., 1., NAN))]); + MockProblem::::new(Vector2::zeros(), vec![Some(Vector3::new(1., 1., f64::NAN))]); let (mut problem, err) = LM::new(&LevenbergMarquardt::new(), problem).err().unwrap(); assert_eq!( err.termination, @@ -56,8 +54,10 @@ fn already_zero() { assert_eq!(problem.calls(), [MockCall::Residuals].as_ref()); assert!(err.objective_function.is_zero()); - let problem = - MockProblem::::new(Vector1::new(10.), vec![Some(Vector1::new(MIN_POSITIVE))]); + let problem = MockProblem::::new( + Vector1::new(10.), + vec![Some(Vector1::new(f64::MIN_POSITIVE))], + ); let (mut problem, err) = LM::new(&LevenbergMarquardt::new(), problem).err().unwrap(); assert_eq!(err.termination, TerminationReason::ResidualsZero); assert_eq!(err.number_of_evaluations, 1); diff --git a/src/lm/test_update_diag.rs b/src/lm/test_update_diag.rs index e991d13..a088b49 100644 --- a/src/lm/test_update_diag.rs +++ b/src/lm/test_update_diag.rs @@ -1,13 +1,9 @@ -use ::core::f64::{INFINITY, NAN}; -use alloc::vec; - -use approx::assert_relative_eq; -use nalgebra::*; - use super::test_helpers::{MockCall, MockProblem}; - use super::{LevenbergMarquardt, TerminationReason, LM}; use crate::qr::PivotedQR; +use alloc::vec; +use approx::assert_relative_eq; +use nalgebra::*; #[test] fn gnorm_and_gtol() { @@ -80,11 +76,11 @@ fn nan_inf_xnorm() { if cfg!(not(feature = "minpack-compat")) { let jacobian = Matrix3x2::new(1., 2., 4., -2., 0.5, 0.1); assert_eq!( - setup(Vector2::new(INFINITY, 0.), jacobian.clone()), + setup(Vector2::new(f64::INFINITY, 0.), jacobian.clone()), TerminationReason::Numerical("subproblem x") ); assert_eq!( - setup(Vector2::new(NAN, 0.), jacobian.clone()), + setup(Vector2::new(f64::NAN, 0.), jacobian.clone()), TerminationReason::Numerical("subproblem x") ); } @@ -96,11 +92,14 @@ fn nan_inf_xnorm() { TerminationReason::Numerical("jacobian") }; assert_eq!( - setup(x.clone(), Matrix3x2::new(INFINITY, 2., 4., -2., 0.5, 0.1)), + setup( + x.clone(), + Matrix3x2::new(f64::INFINITY, 2., 4., -2., 0.5, 0.1) + ), termination_reason ); assert_eq!( - setup(x.clone(), Matrix3x2::new(NAN, 2., 4., -2., 0.5, 0.1)), + setup(x.clone(), Matrix3x2::new(f64::NAN, 2., 4., -2., 0.5, 0.1)), termination_reason ); } diff --git a/src/qr.rs b/src/qr.rs index d191363..9afc1b6 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -33,7 +33,7 @@ where M: Dim + DimMin, N: Dim, S: RawStorageMut + IsContiguous, - DefaultAllocator: Allocator + Allocator, + DefaultAllocator: Allocator, { /// The column norms of the input matrix `$\mathbf{A}$` column_norms: OVector, @@ -54,7 +54,7 @@ where M: Dim + DimMin + DimMax, N: Dim, S: RawStorageMut + Storage + IsContiguous, - DefaultAllocator: Allocator + Allocator, N> + Allocator, + DefaultAllocator: Allocator + Allocator, N>, { /// Create a pivoted QR decomposition of a matrix `$\mathbf{A}\in\R^{m\times n}$`. pub fn new(mut a: Matrix) -> Self { @@ -203,7 +203,7 @@ where F: nalgebra::RealField + Float + Copy, M: Dim + DimMax, N: Dim, - DefaultAllocator: Allocator + Allocator, N> + Allocator, + DefaultAllocator: Allocator + Allocator, N>, { /// The first `$n$` entries of `$\mathbf{Q}^\top \vec{b}$`. qt_b: OVector, @@ -224,7 +224,7 @@ where F: nalgebra::RealField + Copy, M: Dim + DimMax, N: Dim, - DefaultAllocator: Allocator + Allocator, N> + Allocator, + DefaultAllocator: Allocator + Allocator, N>, { pub permutation: &'a OVector, l: &'a OMatrix, N>, @@ -239,7 +239,7 @@ where F: nalgebra::RealField + Copy, M: Dim + DimMin + DimMax, N: Dim, - DefaultAllocator: Allocator + Allocator, N> + Allocator, + DefaultAllocator: Allocator + Allocator, N> + Allocator, { /// Solve the equation `$\mathbf{L}\vec{x} = \mathbf{P}^\top \vec{b}$`. pub fn solve(&mut self, mut rhs: OVector) -> OVector { @@ -295,7 +295,7 @@ where F: nalgebra::RealField + Float + Copy, M: Dim + DimMin + DimMax, N: Dim, - DefaultAllocator: Allocator + Allocator, N> + Allocator, + DefaultAllocator: Allocator + Allocator, N>, { /// Compute scaled maximum of dot products between `$\vec{b}$` and the columns of `$\mathbf{A}$`. /// @@ -854,7 +854,6 @@ fn test_cholesky_upper() { #[test] fn test_column_max_norm() { - use ::core::f64::NAN; use nalgebra::*; let a = Matrix4x3::from_column_slice(&[ 14., -12., 20., -11., 19., 38., -4., -11., -14., 12., -20., 11., @@ -867,7 +866,18 @@ fn test_column_max_norm() { assert_relative_eq!(max_at_b.unwrap(), 0.88499332, epsilon = 1e-8); let a = Matrix4x3::from_column_slice(&[ - NAN, -12., 20., -11., 19., 38., -4., -11., -14., 12., -20., 11., + f64::NAN, + -12., + 20., + -11., + 19., + 38., + -4., + -11., + -14., + 12., + -20., + 11., ]); let qr = PivotedQR::new(a); let b = Vector4::new(1., 2., 3., 4.); diff --git a/src/trust_region.rs b/src/trust_region.rs index 3f2f999..ee34f3d 100644 --- a/src/trust_region.rs +++ b/src/trust_region.rs @@ -11,7 +11,7 @@ use num_traits::Float; pub struct LMParameter where - DefaultAllocator: Allocator, + DefaultAllocator: Allocator, { pub step: OVector, pub lambda: F, @@ -59,7 +59,7 @@ where F: RealField + Float, N: Dim, M: Dim + DimMin + DimMax, - DefaultAllocator: Allocator + Allocator, N> + Allocator, + DefaultAllocator: Allocator + Allocator, N>, { const P1: f64 = 0.1; debug_assert!(delta.is_positive()); diff --git a/src/utils.rs b/src/utils.rs index 3900a47..8158f4d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,3 +1,4 @@ +#![allow(unexpected_cfgs)] use crate::LeastSquaresProblem; use alloc::{format, string::String}; use core::cell::RefCell; @@ -109,7 +110,7 @@ where M: Dim, O: LeastSquaresProblem, O::JacobianStorage: Clone, - DefaultAllocator: Allocator, + DefaultAllocator: Allocator = O::JacobianStorage>, { let params = problem.params(); let n = params.data.shape().0; @@ -217,9 +218,8 @@ where N: Dim, M: Dim, O: LeastSquaresProblem, M, N>, - DefaultAllocator: Allocator, N, Buffer = O::ParameterStorage> - + Allocator - + Allocator, + DefaultAllocator: + Allocator> = O::ParameterStorage> + Allocator + Allocator, { let mut params = problem.params(); assert!(params.iter().all(|x| x.im.is_zero()), "params must be real");