|
66 | 66 | (newtype)((m11, m21, m12, m22))
|
67 | 67 | end
|
68 | 68 |
|
69 |
| -# TODO add special case for 3x3 matrices |
70 |
| -if VERSION < v"0.7-" |
71 |
| - @inline _exp(s::Size, A::StaticArray) = s(Base.expm(Array(A))) |
72 |
| -else |
73 |
| - @inline _exp(s::Size, A::StaticArray) = s(Base.exp(Array(A))) |
| 69 | +# Adapted from implementation in Base; algorithm from |
| 70 | +# Higham, "Functions of Matrices: Theory and Computation", SIAM, 2008 |
| 71 | +function _exp(::Size, A::StaticMatrix{<:Any,<:Any,T}) where T |
| 72 | + # omitted: matrix balancing, i.e., LAPACK.gebal! |
| 73 | + nA = maximum(sum(abs.(A), Val{1})) # marginally more performant than norm(A, 1) |
| 74 | + ## For sufficiently small nA, use lower order Padé-Approximations |
| 75 | + if (nA <= 2.1) |
| 76 | + A2 = A*A |
| 77 | + if nA > 0.95 |
| 78 | + U = @evalpoly(A2, T(8821612800)*I, T(302702400)*I, T(2162160)*I, T(3960)*I, T(1)*I) |
| 79 | + U = A*U |
| 80 | + V = @evalpoly(A2, T(17643225600)*I, T(2075673600)*I, T(30270240)*I, T(110880)*I, T(90)*I) |
| 81 | + elseif nA > 0.25 |
| 82 | + U = @evalpoly(A2, T(8648640)*I, T(277200)*I, T(1512)*I, T(1)*I) |
| 83 | + U = A*U |
| 84 | + V = @evalpoly(A2, T(17297280)*I, T(1995840)*I, T(25200)*I, T(56)*I) |
| 85 | + elseif nA > 0.015 |
| 86 | + U = @evalpoly(A2, T(15120)*I, T(420)*I, T(1)*I) |
| 87 | + U = A*U |
| 88 | + V = @evalpoly(A2, T(30240)*I, T(3360)*I, T(30)*I) |
| 89 | + else |
| 90 | + U = @evalpoly(A2, T(60)*I, T(1)*I) |
| 91 | + U = A*U |
| 92 | + V = @evalpoly(A2, T(120)*I, T(12)*I) |
| 93 | + end |
| 94 | + expA = (V - U) \ (V + U) |
| 95 | + else |
| 96 | + s = log2(nA/5.4) # power of 2 later reversed by squaring |
| 97 | + if s > 0 |
| 98 | + si = ceil(Int,s) |
| 99 | + A = A / T(2^si) |
| 100 | + end |
| 101 | + |
| 102 | + A2 = A*A |
| 103 | + A4 = A2*A2 |
| 104 | + A6 = A2*A4 |
| 105 | + |
| 106 | + U = A6*(T(1)*A6 + T(16380)*A4 + T(40840800)*A2) + |
| 107 | + (T(33522128640)*A6 + T(10559470521600)*A4 + T(1187353796428800)*A2) + |
| 108 | + T(32382376266240000)*I |
| 109 | + U = A*U |
| 110 | + V = A6*(T(182)*A6 + T(960960)*A4 + T(1323241920)*A2) + |
| 111 | + (T(670442572800)*A6 + T(129060195264000)*A4 + T(7771770303897600)*A2) + |
| 112 | + T(64764752532480000)*I |
| 113 | + expA = (V - U) \ (V + U) |
| 114 | + |
| 115 | + if s > 0 # squaring to reverse dividing by power of 2 |
| 116 | + for t=1:si |
| 117 | + expA = expA*expA |
| 118 | + end |
| 119 | + end |
| 120 | + end |
| 121 | + |
| 122 | + expA |
74 | 123 | end
|
0 commit comments