dimforge / dimforge/nalgebra

SVD: Occasional loss of accuracy

Open
#1,172 10 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
4.8k
Forks
565
PR merge metrics
No merged PRs in 30d

Description

Hi, I haven't been using nalgebra long, and I am not an expert with SVD functionality, so I'm not 100% sure if this is an issue with nalgebra or me.

I am using SVD for alignment of 3d points using random point clouds, and random transformations (the euler angle is random, the rotation matrix is valid). Occasionally, the alignment is poor.

I have traced this back to what appears to be low accuracy in the SVD result, that is, u * s * v_t does not yield the same matrix that the svd was performed on.

Example:
H:
│ 0.24777976656646927 0.5496207895780494 -0.7403583528727136 │
│ 0.5832953614864118 -0.38015695826419854 -0.03392366142812886 │
│ -0.3738110622901052 0.359160059894174 -0.09620293929130566 │

nalgebra svd produced:
u:
│ -0.873792828198889 0.47077673362678457 0.1218825683347777 │
│ 0.31813462431343165 0.7429469762516004 -0.5889143836684206 │
│ -0.3677994755313523 -0.4758140997850944 -0.7989521188685604 │

s:
│ 0.9999999999999996 0 0 │
│ 0 0.8220531474729237 0 │
│ 0 0 0.00000000000000012761238385273053 │

v (this is the transpose of v_t produced by the svd):
│ 0.1065457803497895 0.885789524773893 0.45169117158794986 │
│ -0.7332946769207143 -0.23679742707193852 0.6373428397117634 │
│ 0.6715109183694628 -0.3991289219449654 0.624314976736623 │

u * s * v_t:
│ 0.24970470373979137 0.5491061976155459 -0.7412257125301849 │
│ 0.574884679370761 -0.3779085371334399 -0.030133882488828305 │
│ -0.3856591637197468 0.36232740366575733 -0.09086428962516223 │

The derived matrix is in error by the 3rd and 4th decimal.

I have tested this same matrix H in Octave (free Matlab) and the SVD results were different but yielded an exact match for the original H matrix when re-combined. I know that SVD can yield different results, but I understood that u * s * v_t will always re-produce the original matrix.

Note: although the copy from octave below only shows 6dp, it was loaded with the full precision presented above, as printed from rust debug.

Octave results for comparison, accurate to at least 6 figures:
H =

0.247780 0.549621 -0.740358
0.583295 -0.380157 -0.033924
-0.373811 0.359160 -0.096203

>> [U,S,V] = svd(H)
U =

0.87379 0.46823 -0.13133
-0.31813 0.75465 0.57384
0.36780 -0.45964 0.80837

S =

Diagonal Matrix

1.0000e+00 0 0
0 8.2189e-01 0
0 0 3.6928e-17

V =

-0.10655 0.88579 0.45169
0.73329 -0.23680 0.63734
-0.67151 -0.39913 0.62431

>> U * S * transpose(V)
ans =

0.247780 0.549621 -0.740358
0.583295 -0.380157 -0.033924
-0.373811 0.359160 -0.096203

Thanks for any help with this.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.