From 47913b40ce8de824013ce472344f05a8b96328f1 Mon Sep 17 00:00:00 2001 From: Jiri Pittner Date: Sat, 5 Sep 2026 09:47:01 +0200 Subject: [PATCH] NRMat svdinverse() --- mat.cc | 25 ++++++++++++++++++------- mat.h | 5 ++++- nonclass.h | 22 +++++++++++++++++++--- t.cc | 16 +++++++++++++++- 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/mat.cc b/mat.cc index 5087ddb..80b6c0e 100644 --- a/mat.cc +++ b/mat.cc @@ -3495,21 +3495,32 @@ copyonwrite(); } - +//cannot be in mat.h - would be undefined for intereger types template<> -NRMat NRMat::inverse() +NRMat NRMat::inverse() const { -NRMat tmp(*this); -return calcinverse(tmp); +return calcinverse(*this); } template<> -NRMat > NRMat >::inverse() +NRMat > NRMat >::inverse() const { -NRMat > tmp(*this); -return calcinverse(tmp); +return calcinverse(*this); } +template<> +NRMat NRMat::svdinverse(const double thr) const +{ +return calcsvdinverse(*this,thr); +} + +template<> +NRMat > NRMat >::svdinverse(const double thr) const +{ +return calcsvdinverse(*this,thr); +} + + diff --git a/mat.h b/mat.h index 06d8862..5c20355 100644 --- a/mat.h +++ b/mat.h @@ -173,7 +173,10 @@ public: void identity() {*this = (T)1;} //! inverse matrix - NRMat inverse(); + NRMat inverse() const; + + //! pseudo-svd-inverse matrix + NRMat svdinverse(const LA_traits::normtype thr=0) const; //! add scalar value to the diagonal elements NRMat & operator+=(const T &a); diff --git a/nonclass.h b/nonclass.h index 029d2db..ac30e98 100644 --- a/nonclass.h +++ b/nonclass.h @@ -249,13 +249,11 @@ extern const typename LA_traits::complextype complexmatrix (const T&, const T extern void cholesky(NRMat &a, bool upper=1); extern void cholesky(NRMat > &a, bool upper=1); -//inverse by means of linear solve, preserving rhs intact +//inverse by means of linear solve, pass by value to preserve argument intact template const NRMat calcinverse(NRMat a, T *det=NULL) { -#ifdef DEBUG if(a.nrows()!=a.ncols()) laerror("inverse() for non-square matrix"); -#endif NRMat result(a.nrows(),a.nrows()); result = (T)1.; a.copyonwrite(); @@ -264,6 +262,24 @@ const NRMat calcinverse(NRMat a, T *det=NULL) return result; } + +//inverse by means of SVD , pass by value to preserve argument intact +template +const NRMat calcsvdinverse(NRMat a, double thr=0) +{ + if(a.nrows()!=a.ncols()) laerror("svdinverse() for non-square matrix"); + int n=a.nrows(); + a.copyonwrite(); + NRMat u(n,n),v(n,n); + NRVec w(n); + singular_decomposition(a,&u,w,&v,true); + for(int i=0; i typename LA_traits::normtype MatrixNorm(const MAT &A, const char norm); diff --git a/t.cc b/t.cc index 81b5cc3..6f96253 100644 --- a/t.cc +++ b/t.cc @@ -4798,7 +4798,7 @@ cout<<"part\n"<>n; @@ -4809,4 +4809,18 @@ if(p!=q) laerror("inverseme failed"); else cout <>n; +NRMat a(n,n); +a.randomize(1.); +NRMat b=a.inverse(); +NRMat c=a.svdinverse(1e-14); +cout<< "inverses diff = "<<(b-c).norm()<