|
| 1 | +@inline inv(A::StaticMatrix) = _inv(Size(A), A) |
1 | 2 |
|
2 |
| -@generated function inv{T}(A::StaticMatrix{T}) |
| 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) |
| 6 | + T = eltype(A) |
| 7 | + S = typeof((one(T)*zero(T) + zero(T))/one(T)) |
| 8 | + newtype = similar_type(A, S) |
| 9 | + |
| 10 | + d = det(A) |
| 11 | + @inbounds return newtype((A[4]/d, -(A[2]/d), -(A[3]/d), A[1]/d)) |
| 12 | +end |
| 13 | + |
| 14 | +@inline function _inv(::Size{(3,3)}, A) |
| 15 | + T = eltype(A) |
3 | 16 | S = typeof((one(T)*zero(T) + zero(T))/one(T))
|
4 | 17 | newtype = similar_type(A, S)
|
5 | 18 |
|
6 |
| - if size(A) == (1,1) |
7 |
| - return quote |
8 |
| - $(Expr(:meta, :inline)) |
9 |
| - @inbounds return $newtype((inv(A[1]),)) |
10 |
| - end |
11 |
| - elseif size(A) == (2,2) |
12 |
| - return quote |
13 |
| - $(Expr(:meta, :inline)) |
14 |
| - d = A[1]*A[4] - A[3]*A[2] |
15 |
| - @inbounds return $newtype((A[4]/d, -A[2]/d, -A[3]/d, A[1]/d)) |
16 |
| - end |
17 |
| - elseif size(A) == (3,3) |
18 |
| - return quote |
19 |
| - $(Expr(:meta, :inline)) |
20 |
| - @inbounds x0 = SVector(A[1], A[2], A[3]) |
21 |
| - @inbounds x1 = SVector(A[4], A[5], A[6]) |
22 |
| - @inbounds x2 = SVector(A[7], A[8], A[9]) |
23 |
| - |
24 |
| - y0 = cross(x1,x2) |
25 |
| - d = vecdot(x0, y0) |
26 |
| - x0 = x0 / d |
27 |
| - y0 = y0 / d |
28 |
| - y1 = cross(x2,x0) |
29 |
| - y2 = cross(x0,x1) |
30 |
| - |
31 |
| - @inbounds return $newtype((y0[1], y1[1], y2[1], y0[2], y1[2], y2[2], y0[3], y1[3], y2[3])) |
32 |
| - end |
| 19 | + @inbounds x0 = SVector(A[1], A[2], A[3]) |
| 20 | + @inbounds x1 = SVector(A[4], A[5], A[6]) |
| 21 | + @inbounds x2 = SVector(A[7], A[8], A[9]) |
| 22 | + |
| 23 | + y0 = cross(x1,x2) |
| 24 | + d = vecdot(x0, y0) |
| 25 | + x0 = x0 / d |
| 26 | + y0 = y0 / d |
| 27 | + y1 = cross(x2,x0) |
| 28 | + y2 = cross(x0,x1) |
| 29 | + |
| 30 | + @inbounds return newtype((y0[1], y1[1], y2[1], y0[2], y1[2], y2[2], y0[3], y1[3], y2[3])) |
| 31 | +end |
| 32 | + |
| 33 | +@inline function _inv(::Size, A) |
| 34 | + T = eltype(A) |
| 35 | + S = typeof((one(T)*zero(T) + zero(T))/one(T)) |
| 36 | + AA = convert(Array{S}, A) # lufact() doesn't work with StaticArrays at the moment... and the branches below must be type-stable |
| 37 | + if istriu(A) |
| 38 | + Ai_ut = inv(UpperTriangular(AA)) |
| 39 | + # TODO double check these routines leave the parent in a clean (upper triangular) state |
| 40 | + return Size(A)(parent(Ai_ut)) # Return a `SizedArray` |
| 41 | + elseif istril(A) |
| 42 | + Ai_lt = inv(LowerTriangular(AA)) |
| 43 | + # TODO double check these routines leave the parent in a clean (lower triangular) state |
| 44 | + return Size(A)(parent(Ai_lt)) # Return a `SizedArray` |
33 | 45 | else
|
34 |
| - return quote # Implementation from Base |
35 |
| - AA = convert(Array{$S}, A) # lufact() doesn't work with StaticArrays at the moment... and the branches below must be type-stable |
36 |
| - if istriu(A) |
37 |
| - Ai = inv(UpperTriangular(AA)) |
38 |
| - elseif istril(A) |
39 |
| - Ai = inv(LowerTriangular(AA)) |
40 |
| - else |
41 |
| - Ai = inv(lufact(AA)) |
42 |
| - end |
43 |
| - # Return a `SizedArray` |
44 |
| - return $(Size(A))(convert(typeof(parent(Ai)), Ai)) |
45 |
| - end |
| 46 | + Ai_lu = inv(lufact(AA)) |
| 47 | + return Size(A)(Ai_lu) # Return a `SizedArray` |
46 | 48 | end
|
47 | 49 | end
|
0 commit comments