-
Notifications
You must be signed in to change notification settings - Fork 152
replace inv and det for 4x4 matrices, #260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a0d168f
02b4890
6301885
0cd325a
3fbb854
cc34e5e
e578b9b
045c1cf
801b43c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,41 @@ | ||
@inline function det(A::StaticMatrix) | ||
T = eltype(A) | ||
S = typeof((one(T)*zero(T) + zero(T))/one(T)) | ||
_det(Size(A),A,S) | ||
A_S = convert(similar_type(A,S),A) | ||
_det(Size(A_S),A_S) | ||
end | ||
|
||
@inline logdet(A::StaticMatrix) = log(det(A)) | ||
|
||
@inline _det(::Size{(1,1)}, A::StaticMatrix,S::Type) = @inbounds return convert(S,A[1]) | ||
@inline _det(::Size{(1,1)}, A::StaticMatrix) = @inbounds return A[1] | ||
|
||
@inline function _det(::Size{(2,2)}, A::StaticMatrix, S::Type) | ||
A = similar_type(A,S)(A) | ||
@inline function _det(::Size{(2,2)}, A::StaticMatrix) | ||
@inbounds return A[1]*A[4] - A[3]*A[2] | ||
end | ||
|
||
@inline function _det(::Size{(3,3)}, A::StaticMatrix, S::Type) | ||
A = similar_type(A,S)(A) | ||
@inline function _det(::Size{(3,3)}, A::StaticMatrix) | ||
@inbounds x0 = SVector(A[1], A[2], A[3]) | ||
@inbounds x1 = SVector(A[4], A[5], A[6]) | ||
@inbounds x2 = SVector(A[7], A[8], A[9]) | ||
return vecdot(x0, cross(x1, x2)) | ||
end | ||
|
||
@inline function _det(::Size, A::StaticMatrix,::Type) | ||
@inline function _det(::Size{(4,4)}, A::StaticMatrix) | ||
@inbounds return ( | ||
A[13] * A[10] * A[7] * A[4] - A[9] * A[14] * A[7] * A[4] - | ||
A[13] * A[6] * A[11] * A[4] + A[5] * A[14] * A[11] * A[4] + | ||
A[9] * A[6] * A[15] * A[4] - A[5] * A[10] * A[15] * A[4] - | ||
A[13] * A[10] * A[3] * A[8] + A[9] * A[14] * A[3] * A[8] + | ||
A[13] * A[2] * A[11] * A[8] - A[1] * A[14] * A[11] * A[8] - | ||
A[9] * A[2] * A[15] * A[8] + A[1] * A[10] * A[15] * A[8] + | ||
A[13] * A[6] * A[3] * A[12] - A[5] * A[14] * A[3] * A[12] - | ||
A[13] * A[2] * A[7] * A[12] + A[1] * A[14] * A[7] * A[12] + | ||
A[5] * A[2] * A[15] * A[12] - A[1] * A[6] * A[15] * A[12] - | ||
A[9] * A[6] * A[3] * A[16] + A[5] * A[10] * A[3] * A[16] + | ||
A[9] * A[2] * A[7] * A[16] - A[1] * A[10] * A[7] * A[16] - | ||
A[5] * A[2] * A[11] * A[16] + A[1] * A[6] * A[11] * A[16]) | ||
end | ||
|
||
@inline function _det(::Size, A::StaticMatrix) | ||
return det(Matrix(A)) | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,14 @@ end | |
sm = SMatrix{4,4}(m) | ||
@test isapprox(inv(sm)::StaticMatrix, inv(m), rtol=2e-15) | ||
|
||
# A permutation matrix which can cause problems for inversion methods | ||
# without pivoting, eg 2x2 block decomposition (see #250) | ||
mperm = [1 0 0 0; | ||
0 0 1 0; | ||
0 1 0 0; | ||
0 0 0 1] | ||
@test inv(SMatrix{4,4}(mperm))::StaticMatrix ≈ inv(mperm) rtol=2e-16 | ||
|
||
# Poorly conditioned matrix; almost_singular_matrix(4, 3, 1e-7) | ||
m = [ | ||
2.83056817904263402e-01 1.26822318692296848e-01 2.59665505365002547e-01 1.24524798964590747e-01 | ||
|
@@ -55,8 +63,8 @@ end | |
1.63327582123091175e-01 1.70552365412100865e-01 4.55720450934200327e-01 1.23299968650232419e-01 | ||
] | ||
sm = SMatrix{4,4}(m) | ||
@test norm(Matrix(sm*inv(sm) - eye(4))) < 10*norm(m*inv(m) - eye(4)) | ||
@test norm(Matrix(inv(sm)*sm - eye(4))) < 10*norm(inv(m)*m - eye(4)) | ||
@test norm(Matrix(sm*inv(sm) - eye(4))) < 12*norm(m*inv(m) - eye(4)) | ||
@test norm(Matrix(inv(sm)*sm - eye(4))) < 12*norm(inv(m)*m - eye(4)) | ||
|
||
# Poorly conditioned matrix, generated by fuzz testing with | ||
# almost_singular_matrix(N, 3, 1e-7) | ||
|
@@ -66,8 +74,8 @@ end | |
3.42945636322714076e-01 3.29329508494837497e-01 2.25635541033857107e-01 6.03912636987153917e-02 | ||
4.77828437366344727e-01 4.86406974015710591e-01 1.95415684569693188e-01 6.74775080892497797e-02] | ||
sm = SMatrix{4,4}(m) | ||
@test_broken norm(Matrix(inv(sm)*sm - eye(4))) < 10*norm(inv(m)*m - eye(4)) | ||
@test_broken norm(Matrix(sm*inv(sm) - eye(4))) < 10*norm(m*inv(m) - eye(4)) | ||
@test norm(Matrix(inv(sm)*sm - eye(4))) < 12*norm(inv(m)*m - eye(4)) | ||
@test norm(Matrix(sm*inv(sm) - eye(4))) < 12*norm(m*inv(m) - eye(4)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These tests were particularly chosen as examples where the previous implementation had trouble. So they're probably not that relevant to the new implementation. Presumably we'd be able to find some equivalent problems by rerunning the code at the bottom of this file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is still a difficult case (as evidenced by the bounds being quite tight). But running the problem generator would be a good idea. |
||
end | ||
|
||
@testset "Matrix inverse 5x5" begin | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is ok I think. There's nothing special about the factor of
10
which you've replaced with 12 here. I'd say some difference is to be expected with a switch in algorithms.