|
1 |
| -@inline inv(A::StaticMatrix) = _inv(Size(A), A) |
2 |
| - |
3 |
| -@inline _inv(::Size{(1,1)}, A) = similar_type(typeof(A), typeof(inv(one(eltype(A)))))(inv(A[1])) |
4 |
| - |
5 |
| -@inline function _inv(::Size{(2,2)}, A) |
| 1 | +@inline function inv(A::StaticMatrix) |
6 | 2 | T = eltype(A)
|
7 | 3 | S = typeof((one(T)*zero(T) + zero(T))/one(T))
|
8 |
| - newtype = similar_type(A, S) |
| 4 | + A_S = convert(similar_type(A,S),A) |
| 5 | + _inv(Size(A_S),A_S) |
| 6 | +end |
| 7 | + |
| 8 | +@inline _inv(::Size{(1,1)}, A) = similar_type(A)(inv(A[1])) |
9 | 9 |
|
10 |
| - d = det(A) |
11 |
| - @inbounds return newtype((A[4]/d, -(A[2]/d), -(A[3]/d), A[1]/d)) |
| 10 | +@inline function _inv(::Size{(2,2)}, A) |
| 11 | + newtype = similar_type(A) |
| 12 | + idet = 1/det(A) |
| 13 | + @inbounds return newtype((A[4]*idet, -(A[2]*idet), -(A[3]*idet), A[1]*idet)) |
12 | 14 | end
|
13 | 15 |
|
14 | 16 | @inline function _inv(::Size{(3,3)}, A)
|
15 |
| - T = eltype(A) |
16 |
| - S = typeof((one(T)*zero(T) + zero(T))/one(T)) |
17 |
| - newtype = similar_type(A, S) |
| 17 | + newtype = similar_type(A) |
18 | 18 |
|
19 |
| - @inbounds x0 = SVector{3,S}(A[1], A[2], A[3]) |
20 |
| - @inbounds x1 = SVector{3,S}(A[4], A[5], A[6]) |
21 |
| - @inbounds x2 = SVector{3,S}(A[7], A[8], A[9]) |
| 19 | + @inbounds x0 = SVector{3}(A[1], A[2], A[3]) |
| 20 | + @inbounds x1 = SVector{3}(A[4], A[5], A[6]) |
| 21 | + @inbounds x2 = SVector{3}(A[7], A[8], A[9]) |
22 | 22 |
|
23 | 23 | y0 = cross(x1,x2)
|
24 | 24 | d = vecdot(x0, y0)
|
|
30 | 30 | @inbounds return newtype((y0[1], y1[1], y2[1], y0[2], y1[2], y2[2], y0[3], y1[3], y2[3]))
|
31 | 31 | end
|
32 | 32 |
|
33 |
| -Base.@pure function splitrange(r::SUnitRange) |
34 |
| - mid = (first(r) + last(r)) ÷ 2 |
35 |
| - (SUnitRange(first(r), mid), SUnitRange(mid+1, last(r))) |
36 |
| -end |
37 |
| - |
38 |
| -@noinline function _inv(::Size{(4,4)}, A) |
39 |
| - # Partition matrix into four 2x2 blocks. For 4x4 matrices this seems to be |
40 |
| - # more stable than directly using the adjugate expansion. |
41 |
| - # See http://www.freevec.org/function/inverse_matrix_4x4_using_partitioning |
42 |
| - # |
43 |
| - # TODO: This decomposition works in higher dimensions, but numerical |
44 |
| - # stability doesn't seem good for badly conditioned matrices. Can be |
45 |
| - # fixed? |
46 |
| - (i1,i2) = splitrange(SUnitRange(1,4)) |
47 |
| - @inbounds P = A[i1,i1] |
48 |
| - @inbounds Q = A[i1,i2] |
49 |
| - @inbounds R = A[i2,i1] |
50 |
| - @inbounds S = A[i2,i2] |
51 |
| - invP = inv(P) |
52 |
| - invP_Q = invP*Q |
53 |
| - S2 = inv(S - R*invP_Q) |
54 |
| - R2 = -S2*(R*invP) |
55 |
| - Q2 = -invP_Q*S2 |
56 |
| - P2 = invP - invP_Q*R2 |
57 |
| - [[P2 Q2]; |
58 |
| - [R2 S2]] |
| 33 | +@inline function _inv(::Size{(4,4)}, A) |
| 34 | + idet = 1/det(A) |
| 35 | + B = @SMatrix [ |
| 36 | + (A[2,3]*A[3,4]*A[4,2] - A[2,4]*A[3,3]*A[4,2] + A[2,4]*A[3,2]*A[4,3] - A[2,2]*A[3,4]*A[4,3] - A[2,3]*A[3,2]*A[4,4] + A[2,2]*A[3,3]*A[4,4]) * idet |
| 37 | + (A[2,4]*A[3,3]*A[4,1] - A[2,3]*A[3,4]*A[4,1] - A[2,4]*A[3,1]*A[4,3] + A[2,1]*A[3,4]*A[4,3] + A[2,3]*A[3,1]*A[4,4] - A[2,1]*A[3,3]*A[4,4]) * idet |
| 38 | + (A[2,2]*A[3,4]*A[4,1] - A[2,4]*A[3,2]*A[4,1] + A[2,4]*A[3,1]*A[4,2] - A[2,1]*A[3,4]*A[4,2] - A[2,2]*A[3,1]*A[4,4] + A[2,1]*A[3,2]*A[4,4]) * idet |
| 39 | + (A[2,3]*A[3,2]*A[4,1] - A[2,2]*A[3,3]*A[4,1] - A[2,3]*A[3,1]*A[4,2] + A[2,1]*A[3,3]*A[4,2] + A[2,2]*A[3,1]*A[4,3] - A[2,1]*A[3,2]*A[4,3]) * idet |
| 40 | + |
| 41 | + (A[1,4]*A[3,3]*A[4,2] - A[1,3]*A[3,4]*A[4,2] - A[1,4]*A[3,2]*A[4,3] + A[1,2]*A[3,4]*A[4,3] + A[1,3]*A[3,2]*A[4,4] - A[1,2]*A[3,3]*A[4,4]) * idet |
| 42 | + (A[1,3]*A[3,4]*A[4,1] - A[1,4]*A[3,3]*A[4,1] + A[1,4]*A[3,1]*A[4,3] - A[1,1]*A[3,4]*A[4,3] - A[1,3]*A[3,1]*A[4,4] + A[1,1]*A[3,3]*A[4,4]) * idet |
| 43 | + (A[1,4]*A[3,2]*A[4,1] - A[1,2]*A[3,4]*A[4,1] - A[1,4]*A[3,1]*A[4,2] + A[1,1]*A[3,4]*A[4,2] + A[1,2]*A[3,1]*A[4,4] - A[1,1]*A[3,2]*A[4,4]) * idet |
| 44 | + (A[1,2]*A[3,3]*A[4,1] - A[1,3]*A[3,2]*A[4,1] + A[1,3]*A[3,1]*A[4,2] - A[1,1]*A[3,3]*A[4,2] - A[1,2]*A[3,1]*A[4,3] + A[1,1]*A[3,2]*A[4,3]) * idet |
| 45 | + |
| 46 | + (A[1,3]*A[2,4]*A[4,2] - A[1,4]*A[2,3]*A[4,2] + A[1,4]*A[2,2]*A[4,3] - A[1,2]*A[2,4]*A[4,3] - A[1,3]*A[2,2]*A[4,4] + A[1,2]*A[2,3]*A[4,4]) * idet |
| 47 | + (A[1,4]*A[2,3]*A[4,1] - A[1,3]*A[2,4]*A[4,1] - A[1,4]*A[2,1]*A[4,3] + A[1,1]*A[2,4]*A[4,3] + A[1,3]*A[2,1]*A[4,4] - A[1,1]*A[2,3]*A[4,4]) * idet |
| 48 | + (A[1,2]*A[2,4]*A[4,1] - A[1,4]*A[2,2]*A[4,1] + A[1,4]*A[2,1]*A[4,2] - A[1,1]*A[2,4]*A[4,2] - A[1,2]*A[2,1]*A[4,4] + A[1,1]*A[2,2]*A[4,4]) * idet |
| 49 | + (A[1,3]*A[2,2]*A[4,1] - A[1,2]*A[2,3]*A[4,1] - A[1,3]*A[2,1]*A[4,2] + A[1,1]*A[2,3]*A[4,2] + A[1,2]*A[2,1]*A[4,3] - A[1,1]*A[2,2]*A[4,3]) * idet |
| 50 | + |
| 51 | + (A[1,4]*A[2,3]*A[3,2] - A[1,3]*A[2,4]*A[3,2] - A[1,4]*A[2,2]*A[3,3] + A[1,2]*A[2,4]*A[3,3] + A[1,3]*A[2,2]*A[3,4] - A[1,2]*A[2,3]*A[3,4]) * idet |
| 52 | + (A[1,3]*A[2,4]*A[3,1] - A[1,4]*A[2,3]*A[3,1] + A[1,4]*A[2,1]*A[3,3] - A[1,1]*A[2,4]*A[3,3] - A[1,3]*A[2,1]*A[3,4] + A[1,1]*A[2,3]*A[3,4]) * idet |
| 53 | + (A[1,4]*A[2,2]*A[3,1] - A[1,2]*A[2,4]*A[3,1] - A[1,4]*A[2,1]*A[3,2] + A[1,1]*A[2,4]*A[3,2] + A[1,2]*A[2,1]*A[3,4] - A[1,1]*A[2,2]*A[3,4]) * idet |
| 54 | + (A[1,2]*A[2,3]*A[3,1] - A[1,3]*A[2,2]*A[3,1] + A[1,3]*A[2,1]*A[3,2] - A[1,1]*A[2,3]*A[3,2] - A[1,2]*A[2,1]*A[3,3] + A[1,1]*A[2,2]*A[3,3]) * idet] |
| 55 | + return similar_type(A)(B) |
59 | 56 | end
|
60 | 57 |
|
61 | 58 | @inline function _inv(::Size, A)
|
62 |
| - T = eltype(A) |
63 |
| - S = typeof((one(T)*zero(T) + zero(T))/one(T)) |
64 |
| - AA = convert(Array{S}, A) # lufact() doesn't work with StaticArrays at the moment... and the branches below must be type-stable |
65 |
| - if istriu(A) |
66 |
| - Ai_ut = inv(UpperTriangular(AA)) |
67 |
| - # TODO double check these routines leave the parent in a clean (upper triangular) state |
68 |
| - return Size(A)(parent(Ai_ut)) # Return a `SizedArray` |
69 |
| - elseif istril(A) |
70 |
| - Ai_lt = inv(LowerTriangular(AA)) |
71 |
| - # TODO double check these routines leave the parent in a clean (lower triangular) state |
72 |
| - return Size(A)(parent(Ai_lt)) # Return a `SizedArray` |
73 |
| - else |
74 |
| - Ai_lu = inv(lufact(AA)) |
75 |
| - return Size(A)(Ai_lu) # Return a `SizedArray` |
76 |
| - end |
| 59 | + similar_type(A)(inv(Matrix(A))) |
77 | 60 | end
|
0 commit comments